summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml1
-rw-r--r--Makefile1
-rw-r--r--go.mod37
-rw-r--r--go.sum78
-rw-r--r--test/integration/ci.go12
-rw-r--r--test/integration/container.go8
-rw-r--r--test/integration/container_test.go16
-rw-r--r--test/integration/ui.go33
-rw-r--r--vendor/dario.cat/mergo/FUNDING.json7
-rw-r--r--vendor/dario.cat/mergo/README.md5
-rw-r--r--vendor/dario.cat/mergo/SECURITY.md4
-rw-r--r--vendor/github.com/Azure/go-ansiterm/SECURITY.md41
-rw-r--r--vendor/github.com/Azure/go-ansiterm/osc_string_state.go18
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/.gitignore23
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/LICENSE22
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/README.md190
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/iterator.go58
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/new_improved.jpegbin0 -> 120935 bytes
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/set.go255
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/sorted.go42
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/threadsafe.go299
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/threadunsafe.go332
-rw-r--r--vendor/github.com/docker/docker/AUTHORS4
-rw-r--r--vendor/github.com/docker/docker/api/common.go2
-rw-r--r--vendor/github.com/docker/docker/api/swagger.yaml93
-rw-r--r--vendor/github.com/docker/docker/api/types/image/image_inspect.go5
-rw-r--r--vendor/github.com/docker/docker/api/types/image/opts.go5
-rw-r--r--vendor/github.com/docker/docker/api/types/registry/registry.go28
-rw-r--r--vendor/github.com/docker/docker/api/types/system/info.go11
-rw-r--r--vendor/github.com/docker/docker/client/container_commit.go2
-rw-r--r--vendor/github.com/docker/docker/client/image_create.go2
-rw-r--r--vendor/github.com/docker/docker/client/image_inspect.go11
-rw-r--r--vendor/github.com/docker/docker/client/image_inspect_opts.go12
-rw-r--r--vendor/github.com/docker/docker/client/image_pull.go2
-rw-r--r--vendor/github.com/docker/docker/client/image_push.go5
-rw-r--r--vendor/github.com/docker/docker/client/image_tag.go2
-rw-r--r--vendor/github.com/docker/docker/client/request.go2
-rw-r--r--vendor/github.com/docker/docker/pkg/archive/archive_deprecated.go259
-rw-r--r--vendor/github.com/docker/docker/pkg/archive/changes_deprecated.go56
-rw-r--r--vendor/github.com/docker/docker/pkg/archive/copy_deprecated.go130
-rw-r--r--vendor/github.com/docker/docker/pkg/archive/dev_freebsd.go7
-rw-r--r--vendor/github.com/docker/docker/pkg/archive/diff_deprecated.go37
-rw-r--r--vendor/github.com/docker/docker/pkg/archive/path_deprecated.go10
-rw-r--r--vendor/github.com/docker/docker/pkg/archive/utils.go42
-rw-r--r--vendor/github.com/docker/docker/pkg/archive/whiteouts_deprecated.go10
-rw-r--r--vendor/github.com/docker/docker/pkg/archive/wrap_deprecated.go14
-rw-r--r--vendor/github.com/docker/docker/pkg/idtools/idtools.go78
-rw-r--r--vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go12
-rw-r--r--vendor/github.com/ebitengine/purego/dlfcn.go8
-rw-r--r--vendor/github.com/ebitengine/purego/dlfcn_darwin.go5
-rw-r--r--vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go40
-rw-r--r--vendor/github.com/go-ole/go-ole/SECURITY.md13
-rw-r--r--vendor/github.com/go-ole/go-ole/appveyor.yml50
-rw-r--r--vendor/github.com/go-ole/go-ole/com.go42
-rw-r--r--vendor/github.com/go-ole/go-ole/idispatch_windows.go3
-rw-r--r--vendor/github.com/go-ole/go-ole/variant.go2
-rw-r--r--vendor/github.com/go-stack/stack/LICENSE.md21
-rw-r--r--vendor/github.com/go-stack/stack/README.md38
-rw-r--r--vendor/github.com/go-stack/stack/stack.go400
-rw-r--r--vendor/github.com/lufia/plan9stats/README.md8
-rw-r--r--vendor/github.com/lufia/plan9stats/cpu.go5
-rw-r--r--vendor/github.com/lufia/plan9stats/disk.go116
-rw-r--r--vendor/github.com/lufia/plan9stats/host.go82
-rw-r--r--vendor/github.com/lufia/plan9stats/int.go9
-rw-r--r--vendor/github.com/moby/go-archive/.gitattributes2
-rw-r--r--vendor/github.com/moby/go-archive/.gitignore1
-rw-r--r--vendor/github.com/moby/go-archive/.golangci.yml33
-rw-r--r--vendor/github.com/moby/go-archive/LICENSE202
-rw-r--r--vendor/github.com/moby/go-archive/archive.go (renamed from vendor/github.com/docker/docker/pkg/archive/archive.go)478
-rw-r--r--vendor/github.com/moby/go-archive/archive_linux.go (renamed from vendor/github.com/docker/docker/pkg/archive/archive_linux.go)0
-rw-r--r--vendor/github.com/moby/go-archive/archive_other.go (renamed from vendor/github.com/docker/docker/pkg/archive/archive_other.go)0
-rw-r--r--vendor/github.com/moby/go-archive/archive_unix.go (renamed from vendor/github.com/docker/docker/pkg/archive/archive_unix.go)46
-rw-r--r--vendor/github.com/moby/go-archive/archive_windows.go (renamed from vendor/github.com/docker/docker/pkg/archive/archive_windows.go)11
-rw-r--r--vendor/github.com/moby/go-archive/changes.go (renamed from vendor/github.com/docker/docker/pkg/archive/changes.go)8
-rw-r--r--vendor/github.com/moby/go-archive/changes_linux.go (renamed from vendor/github.com/docker/docker/pkg/archive/changes_linux.go)9
-rw-r--r--vendor/github.com/moby/go-archive/changes_other.go (renamed from vendor/github.com/docker/docker/pkg/archive/changes_other.go)0
-rw-r--r--vendor/github.com/moby/go-archive/changes_unix.go (renamed from vendor/github.com/docker/docker/pkg/archive/changes_unix.go)0
-rw-r--r--vendor/github.com/moby/go-archive/changes_windows.go (renamed from vendor/github.com/docker/docker/pkg/archive/changes_windows.go)0
-rw-r--r--vendor/github.com/moby/go-archive/compression/compression.go263
-rw-r--r--vendor/github.com/moby/go-archive/compression/compression_detect.go65
-rw-r--r--vendor/github.com/moby/go-archive/copy.go (renamed from vendor/github.com/docker/docker/pkg/archive/copy.go)3
-rw-r--r--vendor/github.com/moby/go-archive/copy_unix.go (renamed from vendor/github.com/docker/docker/pkg/archive/copy_unix.go)0
-rw-r--r--vendor/github.com/moby/go-archive/copy_windows.go (renamed from vendor/github.com/docker/docker/pkg/archive/copy_windows.go)0
-rw-r--r--vendor/github.com/moby/go-archive/dev_freebsd.go9
-rw-r--r--vendor/github.com/moby/go-archive/dev_unix.go (renamed from vendor/github.com/docker/docker/pkg/archive/dev_unix.go)0
-rw-r--r--vendor/github.com/moby/go-archive/diff.go (renamed from vendor/github.com/docker/docker/pkg/archive/diff.go)19
-rw-r--r--vendor/github.com/moby/go-archive/diff_unix.go (renamed from vendor/github.com/docker/docker/pkg/archive/diff_unix.go)0
-rw-r--r--vendor/github.com/moby/go-archive/diff_windows.go (renamed from vendor/github.com/docker/docker/pkg/archive/diff_windows.go)0
-rw-r--r--vendor/github.com/moby/go-archive/path.go (renamed from vendor/github.com/docker/docker/pkg/archive/path.go)0
-rw-r--r--vendor/github.com/moby/go-archive/path_unix.go (renamed from vendor/github.com/docker/docker/pkg/archive/path_unix.go)0
-rw-r--r--vendor/github.com/moby/go-archive/path_windows.go (renamed from vendor/github.com/docker/docker/pkg/archive/path_windows.go)0
-rw-r--r--vendor/github.com/moby/go-archive/tarheader/tarheader.go67
-rw-r--r--vendor/github.com/moby/go-archive/tarheader/tarheader_unix.go46
-rw-r--r--vendor/github.com/moby/go-archive/tarheader/tarheader_windows.go12
-rw-r--r--vendor/github.com/moby/go-archive/time.go (renamed from vendor/github.com/docker/docker/pkg/archive/time.go)0
-rw-r--r--vendor/github.com/moby/go-archive/time_nonwindows.go (renamed from vendor/github.com/docker/docker/pkg/archive/time_nonwindows.go)0
-rw-r--r--vendor/github.com/moby/go-archive/time_windows.go (renamed from vendor/github.com/docker/docker/pkg/archive/time_windows.go)0
-rw-r--r--vendor/github.com/moby/go-archive/whiteouts.go (renamed from vendor/github.com/docker/docker/pkg/archive/whiteouts.go)0
-rw-r--r--vendor/github.com/moby/go-archive/wrap.go (renamed from vendor/github.com/docker/docker/pkg/archive/wrap.go)0
-rw-r--r--vendor/github.com/moby/go-archive/xattr_supported.go (renamed from vendor/github.com/docker/docker/pkg/archive/xattr_supported.go)0
-rw-r--r--vendor/github.com/moby/go-archive/xattr_supported_linux.go (renamed from vendor/github.com/docker/docker/pkg/archive/xattr_supported_linux.go)0
-rw-r--r--vendor/github.com/moby/go-archive/xattr_supported_unix.go (renamed from vendor/github.com/docker/docker/pkg/archive/xattr_supported_unix.go)0
-rw-r--r--vendor/github.com/moby/go-archive/xattr_unsupported.go (renamed from vendor/github.com/docker/docker/pkg/archive/xattr_unsupported.go)0
-rw-r--r--vendor/github.com/moby/sys/sequential/sequential_unix.go27
-rw-r--r--vendor/github.com/moby/sys/sequential/sequential_windows.go89
-rw-r--r--vendor/github.com/moby/sys/user/idtools.go141
-rw-r--r--vendor/github.com/moby/sys/user/idtools_unix.go (renamed from vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go)63
-rw-r--r--vendor/github.com/moby/sys/user/idtools_windows.go13
-rw-r--r--vendor/github.com/moby/sys/user/user.go1
-rw-r--r--vendor/github.com/moby/term/term_unix.go2
-rw-r--r--vendor/github.com/playwright-community/playwright-go/.gitattributes3
-rw-r--r--vendor/github.com/playwright-community/playwright-go/.gitignore34
-rw-r--r--vendor/github.com/playwright-community/playwright-go/.gitmodules3
-rw-r--r--vendor/github.com/playwright-community/playwright-go/.golangci.yaml6
-rw-r--r--vendor/github.com/playwright-community/playwright-go/.nojekyll0
-rw-r--r--vendor/github.com/playwright-community/playwright-go/404.html25
-rw-r--r--vendor/github.com/playwright-community/playwright-go/CONTRIBUTING.md39
-rw-r--r--vendor/github.com/playwright-community/playwright-go/Dockerfile.example25
-rw-r--r--vendor/github.com/playwright-community/playwright-go/LICENSE21
-rw-r--r--vendor/github.com/playwright-community/playwright-go/README.md148
-rw-r--r--vendor/github.com/playwright-community/playwright-go/_config.yml21
-rw-r--r--vendor/github.com/playwright-community/playwright-go/apiresponse_assertions.go75
-rw-r--r--vendor/github.com/playwright-community/playwright-go/artifact.go70
-rw-r--r--vendor/github.com/playwright-community/playwright-go/assertions.go146
-rw-r--r--vendor/github.com/playwright-community/playwright-go/binding_call.go87
-rw-r--r--vendor/github.com/playwright-community/playwright-go/browser.go274
-rw-r--r--vendor/github.com/playwright-community/playwright-go/browser_context.go914
-rw-r--r--vendor/github.com/playwright-community/playwright-go/browser_type.go181
-rw-r--r--vendor/github.com/playwright-community/playwright-go/cdp_session.go38
-rw-r--r--vendor/github.com/playwright-community/playwright-go/channel.go92
-rw-r--r--vendor/github.com/playwright-community/playwright-go/channel_owner.go122
-rw-r--r--vendor/github.com/playwright-community/playwright-go/clock.go111
-rw-r--r--vendor/github.com/playwright-community/playwright-go/cmd/playwright/main.go25
-rw-r--r--vendor/github.com/playwright-community/playwright-go/connection.go401
-rw-r--r--vendor/github.com/playwright-community/playwright-go/console_message.go47
-rw-r--r--vendor/github.com/playwright-community/playwright-go/dialog.go48
-rw-r--r--vendor/github.com/playwright-community/playwright-go/download.go56
-rw-r--r--vendor/github.com/playwright-community/playwright-go/element_handle.go403
-rw-r--r--vendor/github.com/playwright-community/playwright-go/errors.go58
-rw-r--r--vendor/github.com/playwright-community/playwright-go/event_emitter.go163
-rw-r--r--vendor/github.com/playwright-community/playwright-go/fetch.go451
-rw-r--r--vendor/github.com/playwright-community/playwright-go/file_chooser.go44
-rw-r--r--vendor/github.com/playwright-community/playwright-go/frame.go792
-rw-r--r--vendor/github.com/playwright-community/playwright-go/frame_locator.go130
-rw-r--r--vendor/github.com/playwright-community/playwright-go/generated-enums.go404
-rw-r--r--vendor/github.com/playwright-community/playwright-go/generated-interfaces.go4658
-rw-r--r--vendor/github.com/playwright-community/playwright-go/generated-structs.go4364
-rw-r--r--vendor/github.com/playwright-community/playwright-go/glob.go170
-rw-r--r--vendor/github.com/playwright-community/playwright-go/har_router.go110
-rw-r--r--vendor/github.com/playwright-community/playwright-go/helpers.go628
-rw-r--r--vendor/github.com/playwright-community/playwright-go/input.go117
-rw-r--r--vendor/github.com/playwright-community/playwright-go/input_files_helper.go202
-rw-r--r--vendor/github.com/playwright-community/playwright-go/internal/safe/map.go90
-rw-r--r--vendor/github.com/playwright-community/playwright-go/js_handle.go421
-rw-r--r--vendor/github.com/playwright-community/playwright-go/jsonPipe.go64
-rw-r--r--vendor/github.com/playwright-community/playwright-go/local_utils.go165
-rw-r--r--vendor/github.com/playwright-community/playwright-go/locator.go914
-rw-r--r--vendor/github.com/playwright-community/playwright-go/locator_assertions.go568
-rw-r--r--vendor/github.com/playwright-community/playwright-go/locator_helpers.go133
-rw-r--r--vendor/github.com/playwright-community/playwright-go/network.go62
-rw-r--r--vendor/github.com/playwright-community/playwright-go/objectFactory.go74
-rw-r--r--vendor/github.com/playwright-community/playwright-go/page.go1384
-rw-r--r--vendor/github.com/playwright-community/playwright-go/page_assertions.go70
-rw-r--r--vendor/github.com/playwright-community/playwright-go/playwright.go64
-rw-r--r--vendor/github.com/playwright-community/playwright-go/request.go274
-rw-r--r--vendor/github.com/playwright-community/playwright-go/response.go162
-rw-r--r--vendor/github.com/playwright-community/playwright-go/route.go270
-rw-r--r--vendor/github.com/playwright-community/playwright-go/run.go409
-rw-r--r--vendor/github.com/playwright-community/playwright-go/run_unix.go10
-rw-r--r--vendor/github.com/playwright-community/playwright-go/run_win.go10
-rw-r--r--vendor/github.com/playwright-community/playwright-go/selectors.go88
-rw-r--r--vendor/github.com/playwright-community/playwright-go/stream.go68
-rw-r--r--vendor/github.com/playwright-community/playwright-go/tracing.go164
-rw-r--r--vendor/github.com/playwright-community/playwright-go/transport.go141
-rw-r--r--vendor/github.com/playwright-community/playwright-go/type_helpers.go72
-rw-r--r--vendor/github.com/playwright-community/playwright-go/video.go97
-rw-r--r--vendor/github.com/playwright-community/playwright-go/waiter.go181
-rw-r--r--vendor/github.com/playwright-community/playwright-go/web_error.go21
-rw-r--r--vendor/github.com/playwright-community/playwright-go/websocket.go134
-rw-r--r--vendor/github.com/playwright-community/playwright-go/websocket_route.go220
-rw-r--r--vendor/github.com/playwright-community/playwright-go/worker.go78
-rw-r--r--vendor/github.com/playwright-community/playwright-go/writable_stream.go44
-rw-r--r--vendor/github.com/power-devops/perfstat/config.go1
-rw-r--r--vendor/github.com/power-devops/perfstat/cpustat.go40
-rw-r--r--vendor/github.com/power-devops/perfstat/diskstat.go1
-rw-r--r--vendor/github.com/power-devops/perfstat/doc.go13
-rw-r--r--vendor/github.com/power-devops/perfstat/fsstat.go1
-rw-r--r--vendor/github.com/power-devops/perfstat/helpers.go57
-rw-r--r--vendor/github.com/power-devops/perfstat/lparstat.go14
-rw-r--r--vendor/github.com/power-devops/perfstat/lvmstat.go1
-rw-r--r--vendor/github.com/power-devops/perfstat/memstat.go1
-rw-r--r--vendor/github.com/power-devops/perfstat/netstat.go1
-rw-r--r--vendor/github.com/power-devops/perfstat/procstat.go1
-rw-r--r--vendor/github.com/power-devops/perfstat/sysconf.go1
-rw-r--r--vendor/github.com/power-devops/perfstat/systemcfg.go59
-rw-r--r--vendor/github.com/power-devops/perfstat/types_disk.go4
-rw-r--r--vendor/github.com/power-devops/perfstat/types_fs.go2
-rw-r--r--vendor/github.com/power-devops/perfstat/types_lpar.go61
-rw-r--r--vendor/github.com/power-devops/perfstat/uptime.go1
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/cpu/cpu_aix_nocgo.go16
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/cpu/cpu_darwin.go15
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/cpu/cpu_dragonfly.go11
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/cpu/cpu_freebsd.go6
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/cpu/cpu_linux.go2
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/cpu/cpu_netbsd.go8
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/cpu/cpu_openbsd.go11
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/cpu/cpu_plan9.go7
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/cpu/cpu_solaris.go36
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/cpu/cpu_windows.go28
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/binary.go8
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/common.go11
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/common_darwin.go11
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/common_linux.go20
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/common_testing.go14
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/common_windows.go22
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/mem/mem_darwin.go6
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/mem/mem_fallback.go6
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/mem/mem_freebsd.go11
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/mem/mem_linux.go2
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/mem/mem_netbsd.go4
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/mem/mem_openbsd.go7
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/mem/mem_plan9.go3
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/mem/mem_solaris.go24
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/mem/mem_windows.go9
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/net/net.go6
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/net/net_aix.go25
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/net/net_aix_cgo.go4
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/net/net_aix_nocgo.go8
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/net/net_darwin.go22
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/net/net_fallback.go14
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/net/net_freebsd.go12
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/net/net_linux.go23
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/net/net_openbsd.go24
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/net/net_solaris.go17
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/net/net_unix.go6
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/net/net_windows.go50
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/process/process.go29
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/process/process_bsd.go26
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/process/process_darwin.go52
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/process/process_fallback.go86
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/process/process_freebsd.go32
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/process/process_linux.go4
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/process/process_openbsd.go44
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/process/process_plan9.go86
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/process/process_posix.go4
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/process/process_solaris.go63
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/process/process_windows.go146
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/process/process_windows_32bit.go74
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/process/process_windows_64bit.go36
-rw-r--r--vendor/github.com/tklauser/go-sysconf/.cirrus.yml10
-rw-r--r--vendor/github.com/tklauser/go-sysconf/sysconf_bsd.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/sysconf_darwin.go37
-rw-r--r--vendor/github.com/tklauser/go-sysconf/sysconf_generic.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/sysconf_linux.go20
-rw-r--r--vendor/github.com/tklauser/go-sysconf/sysconf_netbsd.go18
-rw-r--r--vendor/github.com/tklauser/go-sysconf/sysconf_posix.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/sysconf_unsupported.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_defs_darwin.go2
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_defs_dragonfly.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_defs_freebsd.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_defs_linux.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_defs_netbsd.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_defs_openbsd.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_defs_solaris.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_386.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_amd64.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_arm.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_arm64.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_riscv64.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_386.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_amd64.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_arm.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_arm64.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_loong64.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips64.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips64le.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mipsle.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_ppc64.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_ppc64le.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_riscv64.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_s390x.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_386.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_amd64.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_arm.go1
-rw-r--r--vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_arm64.go1
-rw-r--r--vendor/github.com/tklauser/numcpus/.cirrus.yml20
-rw-r--r--vendor/github.com/tklauser/numcpus/numcpus.go23
-rw-r--r--vendor/github.com/tklauser/numcpus/numcpus_bsd.go1
-rw-r--r--vendor/github.com/tklauser/numcpus/numcpus_linux.go104
-rw-r--r--vendor/github.com/tklauser/numcpus/numcpus_list_unsupported.go33
-rw-r--r--vendor/github.com/tklauser/numcpus/numcpus_solaris.go1
-rw-r--r--vendor/github.com/tklauser/numcpus/numcpus_unsupported.go1
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/client.go6
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go7
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go58
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go3
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/gen.go10
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go14
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go204
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/gen.go14
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go225
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go28
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go135
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go11
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/start_time_context.go29
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go58
-rw-r--r--vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go2
-rw-r--r--vendor/modules.txt58
309 files changed, 27795 insertions, 1752 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e9a09b1..33c2f51 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -58,5 +58,4 @@ integration:
DOCKER_HOST: "tcp://docker:2375"
DOCKER_TLS_CERTDIR: ""
IMAGE_TAG: $CONTAINER_IMAGE_COMMIT
- SKIP_E2E: "true"
# TESTCONTAINERS_HOST_OVERRIDE: "host.docker.internal"
diff --git a/Makefile b/Makefile
index 9c43fff..643db68 100644
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,7 @@ setup:
@mise install
@go install tool
@command -v godotenv
+ @command -v playwright
@command -v yamlfmt
build: bin/sparkled
diff --git a/go.mod b/go.mod
index 4711563..78a615a 100644
--- a/go.mod
+++ b/go.mod
@@ -4,6 +4,8 @@ go 1.24.0
require (
github.com/coreos/go-oidc/v3 v3.14.1
+ github.com/docker/docker v28.1.1+incompatible
+ github.com/docker/go-connections v0.5.0
github.com/oauth2-proxy/mockoidc v0.0.0-20240214162133-caebfff84d25
github.com/oklog/ulid v1.3.1
github.com/rs/zerolog v1.34.0
@@ -14,8 +16,8 @@ require (
)
require (
- dario.cat/mergo v1.0.1 // indirect
- github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
+ dario.cat/mergo v1.0.2 // indirect
+ github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect
github.com/braydonk/yaml v0.9.0 // indirect
@@ -24,17 +26,17 @@ require (
github.com/containerd/platforms v0.2.1 // indirect
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/deckarep/golang-set/v2 v2.7.0 // indirect
github.com/distribution/reference v0.6.0 // indirect
- github.com/docker/docker v28.0.4+incompatible // indirect
- github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
- github.com/ebitengine/purego v0.8.2 // indirect
+ github.com/ebitengine/purego v0.8.3 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-jose/go-jose/v3 v3.0.4 // indirect
github.com/go-jose/go-jose/v4 v4.1.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
- github.com/go-ole/go-ole v1.2.6 // indirect
+ github.com/go-ole/go-ole v1.3.0 // indirect
+ github.com/go-stack/stack v1.8.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/golobby/container/v3 v3.3.2 // indirect
@@ -44,36 +46,38 @@ require (
github.com/google/yamlfmt v0.16.0 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/klauspost/compress v1.18.0 // indirect
- github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
+ github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect
github.com/magiconair/properties v1.8.10 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
+ github.com/moby/go-archive v0.1.0 // indirect
github.com/moby/patternmatcher v0.6.0 // indirect
- github.com/moby/sys/sequential v0.5.0 // indirect
- github.com/moby/sys/user v0.1.0 // indirect
+ github.com/moby/sys/atomicwriter v0.1.0 // indirect
+ github.com/moby/sys/sequential v0.6.0 // indirect
+ github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
- github.com/moby/term v0.5.0 // indirect
+ github.com/moby/term v0.5.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
+ github.com/playwright-community/playwright-go v0.5200.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
+ github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 // indirect
- github.com/shirou/gopsutil/v4 v4.25.1 // indirect
+ github.com/shirou/gopsutil/v4 v4.25.4 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
- github.com/tklauser/go-sysconf v0.3.12 // indirect
- github.com/tklauser/numcpus v0.6.1 // indirect
+ github.com/tklauser/go-sysconf v0.3.15 // indirect
+ github.com/tklauser/numcpus v0.10.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
- go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
- go.opentelemetry.io/otel/sdk v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
golang.org/x/crypto v0.38.0 // indirect
@@ -88,4 +92,5 @@ require (
tool (
github.com/google/yamlfmt/cmd/yamlfmt
github.com/joho/godotenv/cmd/godotenv
+ github.com/playwright-community/playwright-go/cmd/playwright
)
diff --git a/go.sum b/go.sum
index d52fa13..bcc21e0 100644
--- a/go.sum
+++ b/go.sum
@@ -1,9 +1,9 @@
-dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
-dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
-github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
-github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
-github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
-github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
+dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
+github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
+github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q=
@@ -26,16 +26,18 @@ github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr
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/deckarep/golang-set/v2 v2.7.0 h1:gIloKvD7yH2oip4VLhsv3JyLLFnC0Y2mlusgcvJYW5k=
+github.com/deckarep/golang-set/v2 v2.7.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
-github.com/docker/docker v28.0.4+incompatible h1:JNNkBctYKurkw6FrHfKqY0nKIDf5nrbxjVBtS+cdcok=
-github.com/docker/docker v28.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v28.1.1+incompatible h1:49M11BFLsVO1gxY9UX9p/zwkE/rswggs8AdFmXQw51I=
+github.com/docker/docker v28.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
-github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I=
-github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
+github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc=
+github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY=
@@ -47,8 +49,11 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
-github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
+github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
+github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
+github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
@@ -56,7 +61,6 @@ github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeD
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golobby/container/v3 v3.3.2 h1:7u+RgNnsdVlhGoS8gY4EXAG601vpMMzLZlYqSp77Quw=
github.com/golobby/container/v3 v3.3.2/go.mod h1:RDdKpnKpV1Of11PFBe7Dxc2C1k2KaLE4FD47FflAmj0=
-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
@@ -78,8 +82,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
-github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
+github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc=
+github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
@@ -93,16 +97,20 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
+github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
+github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
-github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
-github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
-github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
-github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
+github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
+github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
+github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
+github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
+github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
+github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
-github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
-github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
+github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
+github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/oauth2-proxy/mockoidc v0.0.0-20240214162133-caebfff84d25 h1:9bCMuD3TcnjeqjPT2gSlha4asp8NvgcFRYExCaikCxk=
@@ -115,10 +123,12 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJw
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/playwright-community/playwright-go v0.5200.0 h1:z/5LGuX2tBrg3ug1HupMXLjIG93f1d2MWdDsNhkMQ9c=
+github.com/playwright-community/playwright-go v0.5200.0/go.mod h1:UnnyQZaqUOO5ywAZu60+N4EiWReUqX1MQBBA3Oofvf8=
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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
-github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
+github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
+github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
@@ -126,8 +136,8 @@ github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
-github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs=
-github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI=
+github.com/shirou/gopsutil/v4 v4.25.4 h1:cdtFO363VEOOFrUCjZRh4XVJkb548lyF0q0uTeMqYPw=
+github.com/shirou/gopsutil/v4 v4.25.4/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -139,10 +149,10 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/testcontainers/testcontainers-go v0.37.0 h1:L2Qc0vkTw2EHWQ08djon0D2uw7Z/PtHS/QzZZ5Ra/hg=
github.com/testcontainers/testcontainers-go v0.37.0/go.mod h1:QPzbxZhQ6Bclip9igjLFj6z0hs01bU8lrl2dHQmgFGM=
-github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
-github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
-github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
-github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
+github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
+github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
+github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
+github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
github.com/xlgmokha/x v0.0.0-20250507172007-444d6e509eb4 h1:5o6TNNvh9RH+/W/XdlNETOgPyUvw9JYESz6IBhjWTKw=
github.com/xlgmokha/x v0.0.0-20250507172007-444d6e509eb4/go.mod h1:FhvU8e/Zcpo0Lw8n5WkPtqQwzGrLD7FhFEi0MbEBLGk=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -152,8 +162,8 @@ github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw=
@@ -164,6 +174,8 @@ go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
+go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
+go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
@@ -208,10 +220,10 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
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.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
@@ -259,5 +271,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
-gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
+gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
+gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
diff --git a/test/integration/ci.go b/test/integration/ci.go
new file mode 100644
index 0000000..5d34685
--- /dev/null
+++ b/test/integration/ci.go
@@ -0,0 +1,12 @@
+package test
+
+import (
+ "testing"
+
+ "github.com/xlgmokha/x/pkg/env"
+)
+
+func isGitlabCI(t *testing.T) bool {
+ t.Logf("CI? %v", env.Fetch("CI", ""))
+ return env.Fetch("CI", "") == "true"
+}
diff --git a/test/integration/container.go b/test/integration/container.go
index 5ce8266..3929697 100644
--- a/test/integration/container.go
+++ b/test/integration/container.go
@@ -60,7 +60,8 @@ func containerOptions(t *testing.T, envVars map[string]string) []testcontainers.
}))
} else {
issuer, port := normalizeIssuer(t, envVars["OIDC_ISSUER"])
- envVars["OIDC_ISSUER"] = issuer
+ // envVars["OIDC_ISSUER"] = issuer
+ t.Logf("issuer: %v, port: %v\n", issuer, port)
options = append(options, testcontainers.WithExposedPorts("8080/tcp", "9901/tcp", "10000/tcp"))
options = append(options, testcontainers.WithHostPortAccess(port))
@@ -68,8 +69,3 @@ func containerOptions(t *testing.T, envVars map[string]string) []testcontainers.
return options
}
-
-func isGitlabCI(t *testing.T) bool {
- t.Logf("CI? %v", env.Fetch("CI", ""))
- return env.Fetch("CI", "") == "true"
-}
diff --git a/test/integration/container_test.go b/test/integration/container_test.go
index 2d68236..6d48beb 100644
--- a/test/integration/container_test.go
+++ b/test/integration/container_test.go
@@ -10,6 +10,7 @@ import (
"time"
"github.com/oauth2-proxy/mockoidc"
+ playwright "github.com/playwright-community/playwright-go"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go"
@@ -78,4 +79,19 @@ func TestContainer(t *testing.T) {
assert.NotEmpty(t, "listener_0", body["configs"])
})
+
+ WithUI(t, func(browser playwright.Browser) {
+ page, err := browser.NewPage()
+ require.NoError(t, err)
+
+ t.Run("initiates an OIDC login", func(t *testing.T) {
+ require.NoError(t, page.Context().ClearCookies())
+ response, err := page.Goto(envoyEndpoint + "/")
+ require.NoError(t, err)
+ assert.True(t, response.Ok())
+
+ require.NoError(t, page.GetByText("Login").Click())
+ assert.Equal(t, srv.AuthorizationEndpoint()+"?client_id="+srv.Config().ClientID, page.URL())
+ })
+ })
}
diff --git a/test/integration/ui.go b/test/integration/ui.go
new file mode 100644
index 0000000..1af0744
--- /dev/null
+++ b/test/integration/ui.go
@@ -0,0 +1,33 @@
+package test
+
+import (
+ "testing"
+
+ playwright "github.com/playwright-community/playwright-go"
+ "github.com/stretchr/testify/require"
+ "github.com/xlgmokha/x/pkg/env"
+ "github.com/xlgmokha/x/pkg/x"
+)
+
+func WithUI(t *testing.T, callback x.Visitor[playwright.Browser]) {
+ t.Run("UI", func(t *testing.T) {
+ if isGitlabCI(t) {
+ t.Skip()
+ }
+ _ = playwright.Install()
+
+ driver, err := playwright.Run()
+ require.NoError(t, err)
+
+ browser, err := driver.Firefox.Launch(playwright.BrowserTypeLaunchOptions{
+ Headless: playwright.Bool(env.Fetch("HEADLESS", "true") == "true"),
+ SlowMo: playwright.Float(1000),
+ })
+ require.NoError(t, err)
+
+ defer browser.Close()
+ defer driver.Stop()
+
+ callback(browser)
+ })
+}
diff --git a/vendor/dario.cat/mergo/FUNDING.json b/vendor/dario.cat/mergo/FUNDING.json
new file mode 100644
index 0000000..0585e1f
--- /dev/null
+++ b/vendor/dario.cat/mergo/FUNDING.json
@@ -0,0 +1,7 @@
+{
+ "drips": {
+ "ethereum": {
+ "ownedBy": "0x6160020e7102237aC41bdb156e94401692D76930"
+ }
+ }
+}
diff --git a/vendor/dario.cat/mergo/README.md b/vendor/dario.cat/mergo/README.md
index 0b3c488..0e4a59a 100644
--- a/vendor/dario.cat/mergo/README.md
+++ b/vendor/dario.cat/mergo/README.md
@@ -85,7 +85,6 @@ Mergo is used by [thousands](https://deps.dev/go/dario.cat%2Fmergo/v1.0.0/depend
* [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
* [go-micro/go-micro](https://github.com/go-micro/go-micro)
* [grafana/loki](https://github.com/grafana/loki)
-* [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
* [masterminds/sprig](github.com/Masterminds/sprig)
* [moby/moby](https://github.com/moby/moby)
* [slackhq/nebula](https://github.com/slackhq/nebula)
@@ -191,10 +190,6 @@ func main() {
}
```
-Note: if test are failing due missing package, please execute:
-
- go get gopkg.in/yaml.v3
-
### Transformers
Transformers allow to merge specific types differently than in the default behavior. In other words, now you can customize how some types are merged. For example, `time.Time` is a struct; it doesn't have zero value but IsZero can return true because it has fields with zero value. How can we merge a non-zero `time.Time`?
diff --git a/vendor/dario.cat/mergo/SECURITY.md b/vendor/dario.cat/mergo/SECURITY.md
index a5de61f..3788fcc 100644
--- a/vendor/dario.cat/mergo/SECURITY.md
+++ b/vendor/dario.cat/mergo/SECURITY.md
@@ -4,8 +4,8 @@
| Version | Supported |
| ------- | ------------------ |
-| 0.3.x | :white_check_mark: |
-| < 0.3 | :x: |
+| 1.x.x | :white_check_mark: |
+| < 1.0 | :x: |
## Security contact information
diff --git a/vendor/github.com/Azure/go-ansiterm/SECURITY.md b/vendor/github.com/Azure/go-ansiterm/SECURITY.md
new file mode 100644
index 0000000..e138ec5
--- /dev/null
+++ b/vendor/github.com/Azure/go-ansiterm/SECURITY.md
@@ -0,0 +1,41 @@
+<!-- BEGIN MICROSOFT SECURITY.MD V0.0.8 BLOCK -->
+
+## Security
+
+Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
+
+If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
+
+## Reporting Security Issues
+
+**Please do not report security vulnerabilities through public GitHub issues.**
+
+Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
+
+If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
+
+You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
+
+Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
+
+ * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
+ * Full paths of source file(s) related to the manifestation of the issue
+ * The location of the affected source code (tag/branch/commit or direct URL)
+ * Any special configuration required to reproduce the issue
+ * Step-by-step instructions to reproduce the issue
+ * Proof-of-concept or exploit code (if possible)
+ * Impact of the issue, including how an attacker might exploit the issue
+
+This information will help us triage your report more quickly.
+
+If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
+
+## Preferred Languages
+
+We prefer all communications to be in English.
+
+## Policy
+
+Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
+
+<!-- END MICROSOFT SECURITY.MD BLOCK -->
diff --git a/vendor/github.com/Azure/go-ansiterm/osc_string_state.go b/vendor/github.com/Azure/go-ansiterm/osc_string_state.go
index 593b10a..194d5e9 100644
--- a/vendor/github.com/Azure/go-ansiterm/osc_string_state.go
+++ b/vendor/github.com/Azure/go-ansiterm/osc_string_state.go
@@ -11,21 +11,13 @@ func (oscState oscStringState) Handle(b byte) (s state, e error) {
return nextState, err
}
- switch {
- case isOscStringTerminator(b):
+ // There are several control characters and sequences which can
+ // terminate an OSC string. Most of them are handled by the baseState
+ // handler. The ANSI_BEL character is a special case which behaves as a
+ // terminator only for an OSC string.
+ if b == ANSI_BEL {
return oscState.parser.ground, nil
}
return oscState, nil
}
-
-// See below for OSC string terminators for linux
-// http://man7.org/linux/man-pages/man4/console_codes.4.html
-func isOscStringTerminator(b byte) bool {
-
- if b == ANSI_BEL || b == 0x5C {
- return true
- }
-
- return false
-}
diff --git a/vendor/github.com/deckarep/golang-set/v2/.gitignore b/vendor/github.com/deckarep/golang-set/v2/.gitignore
new file mode 100644
index 0000000..4eb156d
--- /dev/null
+++ b/vendor/github.com/deckarep/golang-set/v2/.gitignore
@@ -0,0 +1,23 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+.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 0000000..efd4827
--- /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 0000000..bb691b1
--- /dev/null
+++ b/vendor/github.com/deckarep/golang-set/v2/README.md
@@ -0,0 +1,190 @@
+![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.
+
+## Psst
+* Hi there, 👋! Do you use or have interest in the [Zig programming language](https://ziglang.org/) created by Andrew Kelley? If so, the golang-set project has a new sibling project: [ziglang-set](https://github.com/deckarep/ziglang-set)! Come check it out!
+
+## Update 12/3/2024
+* Packaged version: `2.7.0` fixes a long-standing bug with *JSON Unmarshaling*. A large refactor in the interest of performance
+introduced this bug and there was no way around it but to revert the code back to how it was previously. The performance
+difference was likely negligible to begin with. JSON Marshaling and Unmarshaling is now properly supported again without
+needing to do workarounds.
+
+## 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 0000000..fc14e70
--- /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 0000000..429752a
--- /dev/null
+++ b/vendor/github.com/deckarep/golang-set/v2/new_improved.jpeg
Binary files differ
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 0000000..292089d
--- /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 0000000..8ee2e70
--- /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 0000000..93f20c8
--- /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 0000000..7e3243b
--- /dev/null
+++ b/vendor/github.com/deckarep/golang-set/v2/threadunsafe.go
@@ -0,0 +1,332 @@
+/*
+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] {
+ t := make(threadUnsafeSet[T])
+ return &t
+}
+
+func newThreadUnsafeSetWithSize[T comparable](cardinality int) *threadUnsafeSet[T] {
+ t := make(threadUnsafeSet[T], cardinality)
+ return &t
+}
+
+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/docker/docker/AUTHORS b/vendor/github.com/docker/docker/AUTHORS
index 88032de..a2e972e 100644
--- a/vendor/github.com/docker/docker/AUTHORS
+++ b/vendor/github.com/docker/docker/AUTHORS
@@ -293,6 +293,7 @@ Brandon Liu <bdon@bdon.org>
Brandon Philips <brandon.philips@coreos.com>
Brandon Rhodes <brandon@rhodesmill.org>
Brendan Dixon <brendand@microsoft.com>
+Brendon Smith <bws@bws.bio>
Brennan Kinney <5098581+polarathene@users.noreply.github.com>
Brent Salisbury <brent.salisbury@docker.com>
Brett Higgins <brhiggins@arbor.net>
@@ -347,6 +348,7 @@ Casey Bisson <casey.bisson@joyent.com>
Catalin Pirvu <pirvu.catalin94@gmail.com>
Ce Gao <ce.gao@outlook.com>
Cedric Davies <cedricda@microsoft.com>
+Cesar Talledo <cesar.talledo@docker.com>
Cezar Sa Espinola <cezarsa@gmail.com>
Chad Swenson <chadswen@gmail.com>
Chance Zibolski <chance.zibolski@gmail.com>
@@ -1281,6 +1283,7 @@ Krasi Georgiev <krasi@vip-consult.solutions>
Krasimir Georgiev <support@vip-consult.co.uk>
Kris-Mikael Krister <krismikael@protonmail.com>
Kristian Haugene <kristian.haugene@capgemini.com>
+Kristian Heljas <kristian@kristian.ee>
Kristina Zabunova <triara.xiii@gmail.com>
Krystian Wojcicki <kwojcicki@sympatico.ca>
Kunal Kushwaha <kushwaha_kunal_v7@lab.ntt.co.jp>
@@ -1712,6 +1715,7 @@ Patrick Hemmer <patrick.hemmer@gmail.com>
Patrick St. laurent <patrick@saint-laurent.us>
Patrick Stapleton <github@gdi2290.com>
Patrik Cyvoct <patrik@ptrk.io>
+Patrik Leifert <patrikleifert@hotmail.com>
pattichen <craftsbear@gmail.com>
Paul "TBBle" Hampson <Paul.Hampson@Pobox.com>
Paul <paul9869@gmail.com>
diff --git a/vendor/github.com/docker/docker/api/common.go b/vendor/github.com/docker/docker/api/common.go
index 2c62cd4..d75c43d 100644
--- a/vendor/github.com/docker/docker/api/common.go
+++ b/vendor/github.com/docker/docker/api/common.go
@@ -3,7 +3,7 @@ package api // import "github.com/docker/docker/api"
// Common constants for daemon and client.
const (
// DefaultVersion of the current REST API.
- DefaultVersion = "1.48"
+ DefaultVersion = "1.49"
// MinSupportedAPIVersion is the minimum API version that can be supported
// by the API server, specified as "major.minor". Note that the daemon
diff --git a/vendor/github.com/docker/docker/api/swagger.yaml b/vendor/github.com/docker/docker/api/swagger.yaml
index 646032d..1183aaf 100644
--- a/vendor/github.com/docker/docker/api/swagger.yaml
+++ b/vendor/github.com/docker/docker/api/swagger.yaml
@@ -19,10 +19,10 @@ produces:
consumes:
- "application/json"
- "text/plain"
-basePath: "/v1.48"
+basePath: "/v1.49"
info:
title: "Docker Engine API"
- version: "1.48"
+ version: "1.49"
x-logo:
url: "https://docs.docker.com/assets/images/logo-docker-main.png"
description: |
@@ -55,8 +55,8 @@ info:
the URL is not supported by the daemon, a HTTP `400 Bad Request` error message
is returned.
- If you omit the version-prefix, the current version of the API (v1.48) is used.
- For example, calling `/info` is the same as calling `/v1.48/info`. Using the
+ If you omit the version-prefix, the current version of the API (v1.49) is used.
+ For example, calling `/info` is the same as calling `/v1.49/info`. Using the
API without a version-prefix is deprecated and will be removed in a future release.
Engine releases in the near future should support this version of the API,
@@ -6856,6 +6856,8 @@ definitions:
description: "The network pool size"
type: "integer"
example: "24"
+ FirewallBackend:
+ $ref: "#/definitions/FirewallInfo"
Warnings:
description: |
List of warnings / informational messages about missing features, or
@@ -6939,6 +6941,37 @@ definitions:
default: "plugins.moby"
example: "plugins.moby"
+ FirewallInfo:
+ description: |
+ Information about the daemon's firewalling configuration.
+
+ This field is currently only used on Linux, and omitted on other platforms.
+ type: "object"
+ x-nullable: true
+ properties:
+ Driver:
+ description: |
+ The name of the firewall backend driver.
+ type: "string"
+ example: "nftables"
+ Info:
+ description: |
+ Information about the firewall backend, provided as
+ "label" / "value" pairs.
+
+ <p><br /></p>
+
+ > **Note**: The information returned in this field, including the
+ > formatting of values and labels, should not be considered stable,
+ > and may change without notice.
+ type: "array"
+ items:
+ type: "array"
+ items:
+ type: "string"
+ example:
+ - ["ReloadedAt", "2025-01-01T00:00:00Z"]
+
# PluginsInfo is a temp struct holding Plugins name
# registered with docker daemon. It is used by Info struct
PluginsInfo:
@@ -6984,32 +7017,6 @@ definitions:
type: "object"
x-nullable: true
properties:
- AllowNondistributableArtifactsCIDRs:
- description: |
- List of IP ranges to which nondistributable artifacts can be pushed,
- using the CIDR syntax [RFC 4632](https://tools.ietf.org/html/4632).
-
- <p><br /></p>
-
- > **Deprecated**: Pushing nondistributable artifacts is now always enabled
- > and this field is always `null`. This field will be removed in a API v1.49.
- type: "array"
- items:
- type: "string"
- example: []
- AllowNondistributableArtifactsHostnames:
- description: |
- List of registry hostnames to which nondistributable artifacts can be
- pushed, using the format `<hostname>[:<port>]` or `<IP address>[:<port>]`.
-
- <p><br /></p>
-
- > **Deprecated**: Pushing nondistributable artifacts is now always enabled
- > and this field is always `null`. This field will be removed in a API v1.49.
- type: "array"
- items:
- type: "string"
- example: []
InsecureRegistryCIDRs:
description: |
List of IP ranges of insecure registries, using the CIDR syntax
@@ -7179,13 +7186,6 @@ definitions:
description: "Actual commit ID of external tool."
type: "string"
example: "cfb82a876ecc11b5ca0977d1733adbe58599088a"
- Expected:
- description: |
- Commit ID of external tool expected by dockerd as set at build time.
-
- **Deprecated**: This field is deprecated and will be omitted in a API v1.49.
- type: "string"
- example: "2d41c047c83e09a6d61d464906feb2a2f3c52aa4"
SwarmInfo:
description: |
@@ -10491,13 +10491,9 @@ paths:
### Image tarball format
- An image tarball contains one directory per image layer (named using its long ID), each containing these files:
-
- - `VERSION`: currently `1.0` - the file format version
- - `json`: detailed layer information, similar to `docker inspect layer_id`
- - `layer.tar`: A tarfile containing the filesystem changes in this layer
+ An image tarball contains [Content as defined in the OCI Image Layout Specification](https://github.com/opencontainers/image-spec/blob/v1.1.1/image-layout.md#content).
- The `layer.tar` file contains `aufs` style `.wh..wh.aufs` files and directories for storing attribute changes and deletions.
+ Additionally, includes the manifest.json file associated with a backwards compatible docker save format.
If the tarball defines a repository, the tarball should also include a `repositories` file at the root that contains a list of repository and tag names mapped to layer IDs.
@@ -10537,6 +10533,7 @@ paths:
If not provided, the full multi-platform image will be saved.
Example: `{"os": "linux", "architecture": "arm", "variant": "v5"}`
+ tags: ["Image"]
/images/get:
get:
summary: "Export several images"
@@ -10571,6 +10568,16 @@ paths:
type: "array"
items:
type: "string"
+ - name: "platform"
+ type: "string"
+ in: "query"
+ description: |
+ JSON encoded OCI platform describing a platform which will be used
+ to select a platform-specific image to be saved if the image is
+ multi-platform.
+ If not provided, the full multi-platform image will be saved.
+
+ Example: `{"os": "linux", "architecture": "arm", "variant": "v5"}`
tags: ["Image"]
/images/load:
post:
diff --git a/vendor/github.com/docker/docker/api/types/image/image_inspect.go b/vendor/github.com/docker/docker/api/types/image/image_inspect.go
index 78e81f0..40d1f97 100644
--- a/vendor/github.com/docker/docker/api/types/image/image_inspect.go
+++ b/vendor/github.com/docker/docker/api/types/image/image_inspect.go
@@ -128,11 +128,12 @@ type InspectResponse struct {
// compatibility.
Descriptor *ocispec.Descriptor `json:"Descriptor,omitempty"`
- // Manifests is a list of image manifests available in this image. It
+ // Manifests is a list of image manifests available in this image. It
// provides a more detailed view of the platform-specific image manifests or
// other image-attached data like build attestations.
//
- // Only available if the daemon provides a multi-platform image store.
+ // Only available if the daemon provides a multi-platform image store, the client
+ // requests manifests AND does not request a specific platform.
//
// WARNING: This is experimental and may change at any time without any backward
// compatibility.
diff --git a/vendor/github.com/docker/docker/api/types/image/opts.go b/vendor/github.com/docker/docker/api/types/image/opts.go
index 919510f..57800e0 100644
--- a/vendor/github.com/docker/docker/api/types/image/opts.go
+++ b/vendor/github.com/docker/docker/api/types/image/opts.go
@@ -106,6 +106,11 @@ type LoadOptions struct {
type InspectOptions struct {
// Manifests returns the image manifests.
Manifests bool
+
+ // Platform selects the specific platform of a multi-platform image to inspect.
+ //
+ // This option is only available for API version 1.49 and up.
+ Platform *ocispec.Platform
}
// SaveOptions holds parameters to save images.
diff --git a/vendor/github.com/docker/docker/api/types/registry/registry.go b/vendor/github.com/docker/docker/api/types/registry/registry.go
index 8117cb0..14c82aa 100644
--- a/vendor/github.com/docker/docker/api/types/registry/registry.go
+++ b/vendor/github.com/docker/docker/api/types/registry/registry.go
@@ -1,3 +1,6 @@
+// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
+//go:build go1.23
+
package registry // import "github.com/docker/docker/api/types/registry"
import (
@@ -15,23 +18,26 @@ type ServiceConfig struct {
InsecureRegistryCIDRs []*NetIPNet `json:"InsecureRegistryCIDRs"`
IndexConfigs map[string]*IndexInfo `json:"IndexConfigs"`
Mirrors []string
+
+ // ExtraFields is for internal use to include deprecated fields on older API versions.
+ ExtraFields map[string]any `json:"-"`
}
// MarshalJSON implements a custom marshaler to include legacy fields
// in API responses.
-func (sc ServiceConfig) MarshalJSON() ([]byte, error) {
- tmp := map[string]interface{}{
- "InsecureRegistryCIDRs": sc.InsecureRegistryCIDRs,
- "IndexConfigs": sc.IndexConfigs,
- "Mirrors": sc.Mirrors,
- }
- if sc.AllowNondistributableArtifactsCIDRs != nil {
- tmp["AllowNondistributableArtifactsCIDRs"] = nil
+func (sc *ServiceConfig) MarshalJSON() ([]byte, error) {
+ type tmp ServiceConfig
+ base, err := json.Marshal((*tmp)(sc))
+ if err != nil {
+ return nil, err
}
- if sc.AllowNondistributableArtifactsHostnames != nil {
- tmp["AllowNondistributableArtifactsHostnames"] = nil
+ var merged map[string]any
+ _ = json.Unmarshal(base, &merged)
+
+ for k, v := range sc.ExtraFields {
+ merged[k] = v
}
- return json.Marshal(tmp)
+ return json.Marshal(merged)
}
// NetIPNet is the net.IPNet type, which can be marshalled and
diff --git a/vendor/github.com/docker/docker/api/types/system/info.go b/vendor/github.com/docker/docker/api/types/system/info.go
index 8a2444d..27173d4 100644
--- a/vendor/github.com/docker/docker/api/types/system/info.go
+++ b/vendor/github.com/docker/docker/api/types/system/info.go
@@ -73,6 +73,7 @@ type Info struct {
SecurityOptions []string
ProductLicense string `json:",omitempty"`
DefaultAddressPools []NetworkAddressPool `json:",omitempty"`
+ FirewallBackend *FirewallInfo `json:"FirewallBackend,omitempty"`
CDISpecDirs []string
Containerd *ContainerdInfo `json:",omitempty"`
@@ -143,7 +144,7 @@ type Commit struct {
// Expected is the commit ID of external tool expected by dockerd as set at build time.
//
// Deprecated: this field is no longer used in API v1.49, but kept for backward-compatibility with older API versions.
- Expected string
+ Expected string `json:",omitempty"`
}
// NetworkAddressPool is a temp struct used by [Info] struct.
@@ -151,3 +152,11 @@ type NetworkAddressPool struct {
Base string
Size int
}
+
+// FirewallInfo describes the firewall backend.
+type FirewallInfo struct {
+ // Driver is the name of the firewall backend driver.
+ Driver string `json:"Driver"`
+ // Info is a list of label/value pairs, containing information related to the firewall.
+ Info [][2]string `json:"Info,omitempty"`
+}
diff --git a/vendor/github.com/docker/docker/client/container_commit.go b/vendor/github.com/docker/docker/client/container_commit.go
index 9b46a1f..4838ac7 100644
--- a/vendor/github.com/docker/docker/client/container_commit.go
+++ b/vendor/github.com/docker/docker/client/container_commit.go
@@ -32,7 +32,7 @@ func (cli *Client) ContainerCommit(ctx context.Context, containerID string, opti
if tagged, ok := ref.(reference.Tagged); ok {
tag = tagged.Tag()
}
- repository = reference.FamiliarName(ref)
+ repository = ref.Name()
}
query := url.Values{}
diff --git a/vendor/github.com/docker/docker/client/image_create.go b/vendor/github.com/docker/docker/client/image_create.go
index 0357051..1aa061e 100644
--- a/vendor/github.com/docker/docker/client/image_create.go
+++ b/vendor/github.com/docker/docker/client/image_create.go
@@ -21,7 +21,7 @@ func (cli *Client) ImageCreate(ctx context.Context, parentReference string, opti
}
query := url.Values{}
- query.Set("fromImage", reference.FamiliarName(ref))
+ query.Set("fromImage", ref.Name())
query.Set("tag", getAPITagFromNamedRef(ref))
if options.Platform != "" {
query.Set("platform", strings.ToLower(options.Platform))
diff --git a/vendor/github.com/docker/docker/client/image_inspect.go b/vendor/github.com/docker/docker/client/image_inspect.go
index 1161195..d88f0f1 100644
--- a/vendor/github.com/docker/docker/client/image_inspect.go
+++ b/vendor/github.com/docker/docker/client/image_inspect.go
@@ -32,6 +32,17 @@ func (cli *Client) ImageInspect(ctx context.Context, imageID string, inspectOpts
query.Set("manifests", "1")
}
+ if opts.apiOptions.Platform != nil {
+ if err := cli.NewVersionError(ctx, "1.49", "platform"); err != nil {
+ return image.InspectResponse{}, err
+ }
+ platform, err := encodePlatform(opts.apiOptions.Platform)
+ if err != nil {
+ return image.InspectResponse{}, err
+ }
+ query.Set("platform", platform)
+ }
+
resp, err := cli.get(ctx, "/images/"+imageID+"/json", query, nil)
defer ensureReaderClosed(resp)
if err != nil {
diff --git a/vendor/github.com/docker/docker/client/image_inspect_opts.go b/vendor/github.com/docker/docker/client/image_inspect_opts.go
index 2607f36..655cbf0 100644
--- a/vendor/github.com/docker/docker/client/image_inspect_opts.go
+++ b/vendor/github.com/docker/docker/client/image_inspect_opts.go
@@ -4,6 +4,7 @@ import (
"bytes"
"github.com/docker/docker/api/types/image"
+ ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
// ImageInspectOption is a type representing functional options for the image inspect operation.
@@ -36,6 +37,17 @@ func ImageInspectWithManifests(manifests bool) ImageInspectOption {
})
}
+// ImageInspectWithPlatform sets platform API option for the image inspect operation.
+// This option is only available for API version 1.49 and up.
+// With this option set, the image inspect operation will return information for the
+// specified platform variant of the multi-platform image.
+func ImageInspectWithPlatform(platform *ocispec.Platform) ImageInspectOption {
+ return imageInspectOptionFunc(func(clientOpts *imageInspectOpts) error {
+ clientOpts.apiOptions.Platform = platform
+ return nil
+ })
+}
+
// ImageInspectWithAPIOpts sets the API options for the image inspect operation.
func ImageInspectWithAPIOpts(opts image.InspectOptions) ImageInspectOption {
return imageInspectOptionFunc(func(clientOpts *imageInspectOpts) error {
diff --git a/vendor/github.com/docker/docker/client/image_pull.go b/vendor/github.com/docker/docker/client/image_pull.go
index 4286942..f5fe85d 100644
--- a/vendor/github.com/docker/docker/client/image_pull.go
+++ b/vendor/github.com/docker/docker/client/image_pull.go
@@ -26,7 +26,7 @@ func (cli *Client) ImagePull(ctx context.Context, refStr string, options image.P
}
query := url.Values{}
- query.Set("fromImage", reference.FamiliarName(ref))
+ query.Set("fromImage", ref.Name())
if !options.All {
query.Set("tag", getAPITagFromNamedRef(ref))
}
diff --git a/vendor/github.com/docker/docker/client/image_push.go b/vendor/github.com/docker/docker/client/image_push.go
index b340bc4..1a343f4 100644
--- a/vendor/github.com/docker/docker/client/image_push.go
+++ b/vendor/github.com/docker/docker/client/image_push.go
@@ -29,7 +29,6 @@ func (cli *Client) ImagePush(ctx context.Context, image string, options image.Pu
return nil, errors.New("cannot push a digest reference")
}
- name := reference.FamiliarName(ref)
query := url.Values{}
if !options.All {
ref = reference.TagNameOnly(ref)
@@ -52,13 +51,13 @@ func (cli *Client) ImagePush(ctx context.Context, image string, options image.Pu
query.Set("platform", string(pJson))
}
- resp, err := cli.tryImagePush(ctx, name, query, options.RegistryAuth)
+ resp, err := cli.tryImagePush(ctx, ref.Name(), query, options.RegistryAuth)
if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil {
newAuthHeader, privilegeErr := options.PrivilegeFunc(ctx)
if privilegeErr != nil {
return nil, privilegeErr
}
- resp, err = cli.tryImagePush(ctx, name, query, newAuthHeader)
+ resp, err = cli.tryImagePush(ctx, ref.Name(), query, newAuthHeader)
}
if err != nil {
return nil, err
diff --git a/vendor/github.com/docker/docker/client/image_tag.go b/vendor/github.com/docker/docker/client/image_tag.go
index ea6b4a1..25c7360 100644
--- a/vendor/github.com/docker/docker/client/image_tag.go
+++ b/vendor/github.com/docker/docker/client/image_tag.go
@@ -26,7 +26,7 @@ func (cli *Client) ImageTag(ctx context.Context, source, target string) error {
ref = reference.TagNameOnly(ref)
query := url.Values{}
- query.Set("repo", reference.FamiliarName(ref))
+ query.Set("repo", ref.Name())
if tagged, ok := ref.(reference.Tagged); ok {
query.Set("tag", tagged.Tag())
}
diff --git a/vendor/github.com/docker/docker/client/request.go b/vendor/github.com/docker/docker/client/request.go
index 2b913aa..4cc6435 100644
--- a/vendor/github.com/docker/docker/client/request.go
+++ b/vendor/github.com/docker/docker/client/request.go
@@ -237,7 +237,7 @@ func (cli *Client) checkResponseErr(serverResp *http.Response) (retErr error) {
}
var daemonErr error
- if serverResp.Header.Get("Content-Type") == "application/json" && (cli.version == "" || versions.GreaterThan(cli.version, "1.23")) {
+ if serverResp.Header.Get("Content-Type") == "application/json" {
var errorResponse types.ErrorResponse
if err := json.Unmarshal(body, &errorResponse); err != nil {
return errors.Wrap(err, "Error reading JSON")
diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_deprecated.go b/vendor/github.com/docker/docker/pkg/archive/archive_deprecated.go
new file mode 100644
index 0000000..5bdbdef
--- /dev/null
+++ b/vendor/github.com/docker/docker/pkg/archive/archive_deprecated.go
@@ -0,0 +1,259 @@
+// Package archive provides helper functions for dealing with archive files.
+package archive
+
+import (
+ "archive/tar"
+ "io"
+ "os"
+
+ "github.com/docker/docker/pkg/idtools"
+ "github.com/moby/go-archive"
+ "github.com/moby/go-archive/compression"
+ "github.com/moby/go-archive/tarheader"
+)
+
+// ImpliedDirectoryMode represents the mode (Unix permissions) applied to directories that are implied by files in a
+// tar, but that do not have their own header entry.
+//
+// Deprecated: use [archive.ImpliedDirectoryMode] instead.
+const ImpliedDirectoryMode = archive.ImpliedDirectoryMode
+
+type (
+ // Compression is the state represents if compressed or not.
+ //
+ // Deprecated: use [compression.Compression] instead.
+ Compression = compression.Compression
+ // WhiteoutFormat is the format of whiteouts unpacked
+ //
+ // Deprecated: use [archive.WhiteoutFormat] instead.
+ WhiteoutFormat = archive.WhiteoutFormat
+
+ // TarOptions wraps the tar options.
+ //
+ // Deprecated: use [archive.TarOptions] instead.
+ TarOptions struct {
+ IncludeFiles []string
+ ExcludePatterns []string
+ Compression compression.Compression
+ NoLchown bool
+ IDMap idtools.IdentityMapping
+ ChownOpts *idtools.Identity
+ IncludeSourceDir bool
+ // WhiteoutFormat is the expected on disk format for whiteout files.
+ // This format will be converted to the standard format on pack
+ // and from the standard format on unpack.
+ WhiteoutFormat archive.WhiteoutFormat
+ // When unpacking, specifies whether overwriting a directory with a
+ // non-directory is allowed and vice versa.
+ NoOverwriteDirNonDir bool
+ // For each include when creating an archive, the included name will be
+ // replaced with the matching name from this map.
+ RebaseNames map[string]string
+ InUserNS bool
+ // Allow unpacking to succeed in spite of failures to set extended
+ // attributes on the unpacked files due to the destination filesystem
+ // not supporting them or a lack of permissions. Extended attributes
+ // were probably in the archive for a reason, so set this option at
+ // your own peril.
+ BestEffortXattrs bool
+ }
+)
+
+// Archiver implements the Archiver interface and allows the reuse of most utility functions of
+// this package with a pluggable Untar function. Also, to facilitate the passing of specific id
+// mappings for untar, an Archiver can be created with maps which will then be passed to Untar operations.
+//
+// Deprecated: use [archive.Archiver] instead.
+type Archiver struct {
+ Untar func(io.Reader, string, *TarOptions) error
+ IDMapping idtools.IdentityMapping
+}
+
+// NewDefaultArchiver returns a new Archiver without any IdentityMapping
+//
+// Deprecated: use [archive.NewDefaultArchiver] instead.
+func NewDefaultArchiver() *Archiver {
+ return &Archiver{Untar: Untar}
+}
+
+const (
+ Uncompressed = compression.None // Deprecated: use [compression.None] instead.
+ Bzip2 = compression.Bzip2 // Deprecated: use [compression.Bzip2] instead.
+ Gzip = compression.Gzip // Deprecated: use [compression.Gzip] instead.
+ Xz = compression.Xz // Deprecated: use [compression.Xz] instead.
+ Zstd = compression.Zstd // Deprecated: use [compression.Zstd] instead.
+)
+
+const (
+ AUFSWhiteoutFormat = archive.AUFSWhiteoutFormat // Deprecated: use [archive.AUFSWhiteoutFormat] instead.
+ OverlayWhiteoutFormat = archive.OverlayWhiteoutFormat // Deprecated: use [archive.OverlayWhiteoutFormat] instead.
+)
+
+// IsArchivePath checks if the (possibly compressed) file at the given path
+// starts with a tar file header.
+//
+// Deprecated: use [archive.IsArchivePath] instead.
+func IsArchivePath(path string) bool {
+ return archive.IsArchivePath(path)
+}
+
+// DetectCompression detects the compression algorithm of the source.
+//
+// Deprecated: use [compression.Detect] instead.
+func DetectCompression(source []byte) archive.Compression {
+ return compression.Detect(source)
+}
+
+// DecompressStream decompresses the archive and returns a ReaderCloser with the decompressed archive.
+//
+// Deprecated: use [compression.DecompressStream] instead.
+func DecompressStream(arch io.Reader) (io.ReadCloser, error) {
+ return compression.DecompressStream(arch)
+}
+
+// CompressStream compresses the dest with specified compression algorithm.
+//
+// Deprecated: use [compression.CompressStream] instead.
+func CompressStream(dest io.Writer, comp compression.Compression) (io.WriteCloser, error) {
+ return compression.CompressStream(dest, comp)
+}
+
+// TarModifierFunc is a function that can be passed to ReplaceFileTarWrapper.
+//
+// Deprecated: use [archive.TarModifierFunc] instead.
+type TarModifierFunc = archive.TarModifierFunc
+
+// ReplaceFileTarWrapper converts inputTarStream to a new tar stream.
+//
+// Deprecated: use [archive.ReplaceFileTarWrapper] instead.
+func ReplaceFileTarWrapper(inputTarStream io.ReadCloser, mods map[string]archive.TarModifierFunc) io.ReadCloser {
+ return archive.ReplaceFileTarWrapper(inputTarStream, mods)
+}
+
+// FileInfoHeaderNoLookups creates a partially-populated tar.Header from fi.
+//
+// Deprecated: use [tarheader.FileInfoHeaderNoLookups] instead.
+func FileInfoHeaderNoLookups(fi os.FileInfo, link string) (*tar.Header, error) {
+ return tarheader.FileInfoHeaderNoLookups(fi, link)
+}
+
+// FileInfoHeader creates a populated Header from fi.
+//
+// Deprecated: use [archive.FileInfoHeader] instead.
+func FileInfoHeader(name string, fi os.FileInfo, link string) (*tar.Header, error) {
+ return archive.FileInfoHeader(name, fi, link)
+}
+
+// ReadSecurityXattrToTarHeader reads security.capability xattr from filesystem
+// to a tar header
+//
+// Deprecated: use [archive.ReadSecurityXattrToTarHeader] instead.
+func ReadSecurityXattrToTarHeader(path string, hdr *tar.Header) error {
+ return archive.ReadSecurityXattrToTarHeader(path, hdr)
+}
+
+// Tar creates an archive from the directory at `path`, and returns it as a
+// stream of bytes.
+//
+// Deprecated: use [archive.Tar] instead.
+func Tar(path string, compression archive.Compression) (io.ReadCloser, error) {
+ return archive.TarWithOptions(path, &archive.TarOptions{Compression: compression})
+}
+
+// TarWithOptions creates an archive with the given options.
+//
+// Deprecated: use [archive.TarWithOptions] instead.
+func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) {
+ return archive.TarWithOptions(srcPath, toArchiveOpt(options))
+}
+
+// Tarballer is a lower-level interface to TarWithOptions.
+//
+// Deprecated: use [archive.Tarballer] instead.
+type Tarballer = archive.Tarballer
+
+// NewTarballer constructs a new tarballer using TarWithOptions.
+//
+// Deprecated: use [archive.Tarballer] instead.
+func NewTarballer(srcPath string, options *TarOptions) (*archive.Tarballer, error) {
+ return archive.NewTarballer(srcPath, toArchiveOpt(options))
+}
+
+// Unpack unpacks the decompressedArchive to dest with options.
+//
+// Deprecated: use [archive.Unpack] instead.
+func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) error {
+ return archive.Unpack(decompressedArchive, dest, toArchiveOpt(options))
+}
+
+// Untar reads a stream of bytes from `archive`, parses it as a tar archive,
+// and unpacks it into the directory at `dest`.
+//
+// Deprecated: use [archive.Untar] instead.
+func Untar(tarArchive io.Reader, dest string, options *TarOptions) error {
+ return archive.Untar(tarArchive, dest, toArchiveOpt(options))
+}
+
+// UntarUncompressed reads a stream of bytes from `tarArchive`, parses it as a tar archive,
+// and unpacks it into the directory at `dest`.
+// The archive must be an uncompressed stream.
+//
+// Deprecated: use [archive.UntarUncompressed] instead.
+func UntarUncompressed(tarArchive io.Reader, dest string, options *TarOptions) error {
+ return archive.UntarUncompressed(tarArchive, dest, toArchiveOpt(options))
+}
+
+// TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other.
+// If either Tar or Untar fails, TarUntar aborts and returns the error.
+func (archiver *Archiver) TarUntar(src, dst string) error {
+ return (&archive.Archiver{
+ Untar: func(reader io.Reader, s string, options *archive.TarOptions) error {
+ return archiver.Untar(reader, s, &TarOptions{
+ IDMap: archiver.IDMapping,
+ })
+ },
+ IDMapping: idtools.ToUserIdentityMapping(archiver.IDMapping),
+ }).TarUntar(src, dst)
+}
+
+// UntarPath untar a file from path to a destination, src is the source tar file path.
+func (archiver *Archiver) UntarPath(src, dst string) error {
+ return (&archive.Archiver{
+ Untar: func(reader io.Reader, s string, options *archive.TarOptions) error {
+ return archiver.Untar(reader, s, &TarOptions{
+ IDMap: archiver.IDMapping,
+ })
+ },
+ IDMapping: idtools.ToUserIdentityMapping(archiver.IDMapping),
+ }).UntarPath(src, dst)
+}
+
+// CopyWithTar creates a tar archive of filesystem path `src`, and
+// unpacks it at filesystem path `dst`.
+// The archive is streamed directly with fixed buffering and no
+// intermediary disk IO.
+func (archiver *Archiver) CopyWithTar(src, dst string) error {
+ return (&archive.Archiver{
+ Untar: func(reader io.Reader, s string, options *archive.TarOptions) error {
+ return archiver.Untar(reader, s, nil)
+ },
+ IDMapping: idtools.ToUserIdentityMapping(archiver.IDMapping),
+ }).CopyWithTar(src, dst)
+}
+
+// CopyFileWithTar emulates the behavior of the 'cp' command-line
+// for a single file. It copies a regular file from path `src` to
+// path `dst`, and preserves all its metadata.
+func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
+ return (&archive.Archiver{
+ Untar: func(reader io.Reader, s string, options *archive.TarOptions) error {
+ return archiver.Untar(reader, s, nil)
+ },
+ IDMapping: idtools.ToUserIdentityMapping(archiver.IDMapping),
+ }).CopyFileWithTar(src, dst)
+}
+
+// IdentityMapping returns the IdentityMapping of the archiver.
+func (archiver *Archiver) IdentityMapping() idtools.IdentityMapping {
+ return archiver.IDMapping
+}
diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_deprecated.go b/vendor/github.com/docker/docker/pkg/archive/changes_deprecated.go
new file mode 100644
index 0000000..48c7523
--- /dev/null
+++ b/vendor/github.com/docker/docker/pkg/archive/changes_deprecated.go
@@ -0,0 +1,56 @@
+package archive
+
+import (
+ "io"
+
+ "github.com/docker/docker/pkg/idtools"
+ "github.com/moby/go-archive"
+)
+
+// ChangeType represents the change
+//
+// Deprecated: use [archive.ChangeType] instead.
+type ChangeType = archive.ChangeType
+
+const (
+ ChangeModify = archive.ChangeModify // Deprecated: use [archive.ChangeModify] instead.
+ ChangeAdd = archive.ChangeAdd // Deprecated: use [archive.ChangeAdd] instead.
+ ChangeDelete = archive.ChangeDelete // Deprecated: use [archive.ChangeDelete] instead.
+)
+
+// Change represents a change.
+//
+// Deprecated: use [archive.Change] instead.
+type Change = archive.Change
+
+// Changes walks the path rw and determines changes for the files in the path,
+// with respect to the parent layers
+//
+// Deprecated: use [archive.Changes] instead.
+func Changes(layers []string, rw string) ([]archive.Change, error) {
+ return archive.Changes(layers, rw)
+}
+
+// FileInfo describes the information of a file.
+//
+// Deprecated: use [archive.FileInfo] instead.
+type FileInfo = archive.FileInfo
+
+// ChangesDirs compares two directories and generates an array of Change objects describing the changes.
+//
+// Deprecated: use [archive.ChangesDirs] instead.
+func ChangesDirs(newDir, oldDir string) ([]archive.Change, error) {
+ return archive.ChangesDirs(newDir, oldDir)
+}
+
+// ChangesSize calculates the size in bytes of the provided changes, based on newDir.
+//
+// Deprecated: use [archive.ChangesSize] instead.
+func ChangesSize(newDir string, changes []archive.Change) int64 {
+ return archive.ChangesSize(newDir, changes)
+}
+
+// ExportChanges produces an Archive from the provided changes, relative to dir.
+func ExportChanges(dir string, changes []archive.Change, idMap idtools.IdentityMapping) (io.ReadCloser, error) {
+ return archive.ExportChanges(dir, changes, idtools.ToUserIdentityMapping(idMap))
+}
diff --git a/vendor/github.com/docker/docker/pkg/archive/copy_deprecated.go b/vendor/github.com/docker/docker/pkg/archive/copy_deprecated.go
new file mode 100644
index 0000000..1901e55
--- /dev/null
+++ b/vendor/github.com/docker/docker/pkg/archive/copy_deprecated.go
@@ -0,0 +1,130 @@
+package archive
+
+import (
+ "io"
+
+ "github.com/moby/go-archive"
+ "github.com/moby/go-archive/compression"
+)
+
+var (
+ ErrNotDirectory = archive.ErrNotDirectory // Deprecated: use [archive.ErrNotDirectory] instead.
+ ErrDirNotExists = archive.ErrDirNotExists // Deprecated: use [archive.ErrDirNotExists] instead.
+ ErrCannotCopyDir = archive.ErrCannotCopyDir // Deprecated: use [archive.ErrCannotCopyDir] instead.
+ ErrInvalidCopySource = archive.ErrInvalidCopySource // Deprecated: use [archive.ErrInvalidCopySource] instead.
+)
+
+// PreserveTrailingDotOrSeparator returns the given cleaned path.
+//
+// Deprecated: use [archive.PreserveTrailingDotOrSeparator] instead.
+func PreserveTrailingDotOrSeparator(cleanedPath string, originalPath string) string {
+ return archive.PreserveTrailingDotOrSeparator(cleanedPath, originalPath)
+}
+
+// SplitPathDirEntry splits the given path between its directory name and its
+// basename.
+//
+// Deprecated: use [archive.SplitPathDirEntry] instead.
+func SplitPathDirEntry(path string) (dir, base string) {
+ return archive.SplitPathDirEntry(path)
+}
+
+// TarResource archives the resource described by the given CopyInfo to a Tar
+// archive.
+//
+// Deprecated: use [archive.TarResource] instead.
+func TarResource(sourceInfo archive.CopyInfo) (content io.ReadCloser, err error) {
+ return archive.TarResource(sourceInfo)
+}
+
+// TarResourceRebase is like TarResource but renames the first path element of
+// items in the resulting tar archive to match the given rebaseName if not "".
+//
+// Deprecated: use [archive.TarResourceRebase] instead.
+func TarResourceRebase(sourcePath, rebaseName string) (content io.ReadCloser, _ error) {
+ return archive.TarResourceRebase(sourcePath, rebaseName)
+}
+
+// TarResourceRebaseOpts does not preform the Tar, but instead just creates the rebase
+// parameters to be sent to TarWithOptions.
+//
+// Deprecated: use [archive.TarResourceRebaseOpts] instead.
+func TarResourceRebaseOpts(sourceBase string, rebaseName string) *TarOptions {
+ filter := []string{sourceBase}
+ return &TarOptions{
+ Compression: compression.None,
+ IncludeFiles: filter,
+ IncludeSourceDir: true,
+ RebaseNames: map[string]string{
+ sourceBase: rebaseName,
+ },
+ }
+}
+
+// CopyInfo holds basic info about the source or destination path of a copy operation.
+//
+// Deprecated: use [archive.CopyInfo] instead.
+type CopyInfo = archive.CopyInfo
+
+// CopyInfoSourcePath stats the given path to create a CopyInfo struct.
+// struct representing that resource for the source of an archive copy
+// operation.
+//
+// Deprecated: use [archive.CopyInfoSourcePath] instead.
+func CopyInfoSourcePath(path string, followLink bool) (archive.CopyInfo, error) {
+ return archive.CopyInfoSourcePath(path, followLink)
+}
+
+// CopyInfoDestinationPath stats the given path to create a CopyInfo
+// struct representing that resource for the destination of an archive copy
+// operation.
+//
+// Deprecated: use [archive.CopyInfoDestinationPath] instead.
+func CopyInfoDestinationPath(path string) (info archive.CopyInfo, err error) {
+ return archive.CopyInfoDestinationPath(path)
+}
+
+// PrepareArchiveCopy prepares the given srcContent archive.
+//
+// Deprecated: use [archive.PrepareArchiveCopy] instead.
+func PrepareArchiveCopy(srcContent io.Reader, srcInfo, dstInfo archive.CopyInfo) (dstDir string, content io.ReadCloser, err error) {
+ return archive.PrepareArchiveCopy(srcContent, srcInfo, dstInfo)
+}
+
+// RebaseArchiveEntries rewrites the given srcContent archive replacing
+// an occurrence of oldBase with newBase at the beginning of entry names.
+//
+// Deprecated: use [archive.RebaseArchiveEntries] instead.
+func RebaseArchiveEntries(srcContent io.Reader, oldBase, newBase string) io.ReadCloser {
+ return archive.RebaseArchiveEntries(srcContent, oldBase, newBase)
+}
+
+// CopyResource performs an archive copy from the given source path to the
+// given destination path.
+//
+// Deprecated: use [archive.CopyResource] instead.
+func CopyResource(srcPath, dstPath string, followLink bool) error {
+ return archive.CopyResource(srcPath, dstPath, followLink)
+}
+
+// CopyTo handles extracting the given content whose
+// entries should be sourced from srcInfo to dstPath.
+//
+// Deprecated: use [archive.CopyTo] instead.
+func CopyTo(content io.Reader, srcInfo archive.CopyInfo, dstPath string) error {
+ return archive.CopyTo(content, srcInfo, dstPath)
+}
+
+// ResolveHostSourcePath decides real path need to be copied.
+//
+// Deprecated: use [archive.ResolveHostSourcePath] instead.
+func ResolveHostSourcePath(path string, followLink bool) (resolvedPath, rebaseName string, _ error) {
+ return archive.ResolveHostSourcePath(path, followLink)
+}
+
+// GetRebaseName normalizes and compares path and resolvedPath.
+//
+// Deprecated: use [archive.GetRebaseName] instead.
+func GetRebaseName(path, resolvedPath string) (string, string) {
+ return archive.GetRebaseName(path, resolvedPath)
+}
diff --git a/vendor/github.com/docker/docker/pkg/archive/dev_freebsd.go b/vendor/github.com/docker/docker/pkg/archive/dev_freebsd.go
deleted file mode 100644
index aa8e291..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/dev_freebsd.go
+++ /dev/null
@@ -1,7 +0,0 @@
-//go:build freebsd
-
-package archive
-
-import "golang.org/x/sys/unix"
-
-var mknod = unix.Mknod
diff --git a/vendor/github.com/docker/docker/pkg/archive/diff_deprecated.go b/vendor/github.com/docker/docker/pkg/archive/diff_deprecated.go
new file mode 100644
index 0000000..dd5e0d5
--- /dev/null
+++ b/vendor/github.com/docker/docker/pkg/archive/diff_deprecated.go
@@ -0,0 +1,37 @@
+package archive
+
+import (
+ "io"
+
+ "github.com/moby/go-archive"
+)
+
+// UnpackLayer unpack `layer` to a `dest`.
+//
+// Deprecated: use [archive.UnpackLayer] instead.
+func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, err error) {
+ return archive.UnpackLayer(dest, layer, toArchiveOpt(options))
+}
+
+// ApplyLayer parses a diff in the standard layer format from `layer`,
+// and applies it to the directory `dest`.
+//
+// Deprecated: use [archive.ApplyLayer] instead.
+func ApplyLayer(dest string, layer io.Reader) (int64, error) {
+ return archive.ApplyLayer(dest, layer)
+}
+
+// ApplyUncompressedLayer parses a diff in the standard layer format from
+// `layer`, and applies it to the directory `dest`.
+//
+// Deprecated: use [archive.ApplyUncompressedLayer] instead.
+func ApplyUncompressedLayer(dest string, layer io.Reader, options *TarOptions) (int64, error) {
+ return archive.ApplyUncompressedLayer(dest, layer, toArchiveOpt(options))
+}
+
+// IsEmpty checks if the tar archive is empty (doesn't contain any entries).
+//
+// Deprecated: use [archive.IsEmpty] instead.
+func IsEmpty(rd io.Reader) (bool, error) {
+ return archive.IsEmpty(rd)
+}
diff --git a/vendor/github.com/docker/docker/pkg/archive/path_deprecated.go b/vendor/github.com/docker/docker/pkg/archive/path_deprecated.go
new file mode 100644
index 0000000..0fa74de
--- /dev/null
+++ b/vendor/github.com/docker/docker/pkg/archive/path_deprecated.go
@@ -0,0 +1,10 @@
+package archive
+
+import "github.com/moby/go-archive"
+
+// CheckSystemDriveAndRemoveDriveLetter verifies that a path is the system drive.
+//
+// Deprecated: use [archive.CheckSystemDriveAndRemoveDriveLetter] instead.
+func CheckSystemDriveAndRemoveDriveLetter(path string) (string, error) {
+ return archive.CheckSystemDriveAndRemoveDriveLetter(path)
+}
diff --git a/vendor/github.com/docker/docker/pkg/archive/utils.go b/vendor/github.com/docker/docker/pkg/archive/utils.go
new file mode 100644
index 0000000..692cf16
--- /dev/null
+++ b/vendor/github.com/docker/docker/pkg/archive/utils.go
@@ -0,0 +1,42 @@
+package archive
+
+import (
+ "github.com/docker/docker/pkg/idtools"
+ "github.com/moby/go-archive"
+)
+
+// ToArchiveOpt converts an [TarOptions] to a [archive.TarOptions].
+//
+// Deprecated: use [archive.TarOptions] instead, this utility is for internal use to transition to the [github.com/moby/go-archive] module.
+func ToArchiveOpt(options *TarOptions) *archive.TarOptions {
+ return toArchiveOpt(options)
+}
+
+func toArchiveOpt(options *TarOptions) *archive.TarOptions {
+ if options == nil {
+ return nil
+ }
+
+ var chownOpts *archive.ChownOpts
+ if options.ChownOpts != nil {
+ chownOpts = &archive.ChownOpts{
+ UID: options.ChownOpts.UID,
+ GID: options.ChownOpts.GID,
+ }
+ }
+
+ return &archive.TarOptions{
+ IncludeFiles: options.IncludeFiles,
+ ExcludePatterns: options.ExcludePatterns,
+ Compression: options.Compression,
+ NoLchown: options.NoLchown,
+ IDMap: idtools.ToUserIdentityMapping(options.IDMap),
+ ChownOpts: chownOpts,
+ IncludeSourceDir: options.IncludeSourceDir,
+ WhiteoutFormat: options.WhiteoutFormat,
+ NoOverwriteDirNonDir: options.NoOverwriteDirNonDir,
+ RebaseNames: options.RebaseNames,
+ InUserNS: options.InUserNS,
+ BestEffortXattrs: options.BestEffortXattrs,
+ }
+}
diff --git a/vendor/github.com/docker/docker/pkg/archive/whiteouts_deprecated.go b/vendor/github.com/docker/docker/pkg/archive/whiteouts_deprecated.go
new file mode 100644
index 0000000..0ab8590
--- /dev/null
+++ b/vendor/github.com/docker/docker/pkg/archive/whiteouts_deprecated.go
@@ -0,0 +1,10 @@
+package archive
+
+import "github.com/moby/go-archive"
+
+const (
+ WhiteoutPrefix = archive.WhiteoutPrefix // Deprecated: use [archive.WhiteoutPrefix] instead.
+ WhiteoutMetaPrefix = archive.WhiteoutMetaPrefix // Deprecated: use [archive.WhiteoutMetaPrefix] instead.
+ WhiteoutLinkDir = archive.WhiteoutLinkDir // Deprecated: use [archive.WhiteoutLinkDir] instead.
+ WhiteoutOpaqueDir = archive.WhiteoutOpaqueDir // Deprecated: use [archive.WhiteoutOpaqueDir] instead.
+)
diff --git a/vendor/github.com/docker/docker/pkg/archive/wrap_deprecated.go b/vendor/github.com/docker/docker/pkg/archive/wrap_deprecated.go
new file mode 100644
index 0000000..e5d3fa9
--- /dev/null
+++ b/vendor/github.com/docker/docker/pkg/archive/wrap_deprecated.go
@@ -0,0 +1,14 @@
+package archive
+
+import (
+ "io"
+
+ "github.com/moby/go-archive"
+)
+
+// Generate generates a new archive from the content provided as input.
+//
+// Deprecated: use [archive.Generate] instead.
+func Generate(input ...string) (io.Reader, error) {
+ return archive.Generate(input...)
+}
diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools.go b/vendor/github.com/docker/docker/pkg/idtools/idtools.go
index d2fbd94..23e90c2 100644
--- a/vendor/github.com/docker/docker/pkg/idtools/idtools.go
+++ b/vendor/github.com/docker/docker/pkg/idtools/idtools.go
@@ -3,11 +3,15 @@ package idtools
import (
"fmt"
"os"
+
+ "github.com/moby/sys/user"
)
// IDMap contains a single entry for user namespace range remapping. An array
// of IDMap entries represents the structure that will be provided to the Linux
// kernel for creating a user namespace.
+//
+// Deprecated: use [user.IDMap] instead.
type IDMap struct {
ContainerID int `json:"container_id"`
HostID int `json:"host_id"`
@@ -17,28 +21,42 @@ type IDMap struct {
// MkdirAllAndChown creates a directory (include any along the path) and then modifies
// ownership to the requested uid/gid. If the directory already exists, this
// function will still change ownership and permissions.
+//
+// Deprecated: use [user.MkdirAllAndChown] instead.
func MkdirAllAndChown(path string, mode os.FileMode, owner Identity) error {
- return mkdirAs(path, mode, owner, true, true)
+ return user.MkdirAllAndChown(path, mode, owner.UID, owner.GID)
}
// MkdirAndChown creates a directory and then modifies ownership to the requested uid/gid.
// If the directory already exists, this function still changes ownership and permissions.
// Note that unlike os.Mkdir(), this function does not return IsExist error
// in case path already exists.
+//
+// Deprecated: use [user.MkdirAndChown] instead.
func MkdirAndChown(path string, mode os.FileMode, owner Identity) error {
- return mkdirAs(path, mode, owner, false, true)
+ return user.MkdirAndChown(path, mode, owner.UID, owner.GID)
}
// MkdirAllAndChownNew creates a directory (include any along the path) and then modifies
// ownership ONLY of newly created directories to the requested uid/gid. If the
// directories along the path exist, no change of ownership or permissions will be performed
+//
+// Deprecated: use [user.MkdirAllAndChown] with the [user.WithOnlyNew] option instead.
func MkdirAllAndChownNew(path string, mode os.FileMode, owner Identity) error {
- return mkdirAs(path, mode, owner, true, false)
+ return user.MkdirAllAndChown(path, mode, owner.UID, owner.GID, user.WithOnlyNew)
}
// GetRootUIDGID retrieves the remapped root uid/gid pair from the set of maps.
// If the maps are empty, then the root uid/gid will default to "real" 0/0
+//
+// Deprecated: use [(user.IdentityMapping).RootPair] instead.
func GetRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) {
+ return getRootUIDGID(uidMap, gidMap)
+}
+
+// getRootUIDGID retrieves the remapped root uid/gid pair from the set of maps.
+// If the maps are empty, then the root uid/gid will default to "real" 0/0
+func getRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) {
uid, err := toHost(0, uidMap)
if err != nil {
return -1, -1, err
@@ -101,11 +119,61 @@ type IdentityMapping struct {
GIDMaps []IDMap `json:"GIDMaps"`
}
+// FromUserIdentityMapping converts a [user.IdentityMapping] to an [idtools.IdentityMapping].
+//
+// Deprecated: use [user.IdentityMapping] directly, this is transitioning to user package.
+func FromUserIdentityMapping(u user.IdentityMapping) IdentityMapping {
+ return IdentityMapping{
+ UIDMaps: fromUserIDMap(u.UIDMaps),
+ GIDMaps: fromUserIDMap(u.GIDMaps),
+ }
+}
+
+func fromUserIDMap(u []user.IDMap) []IDMap {
+ if u == nil {
+ return nil
+ }
+ m := make([]IDMap, len(u))
+ for i := range u {
+ m[i] = IDMap{
+ ContainerID: int(u[i].ID),
+ HostID: int(u[i].ParentID),
+ Size: int(u[i].Count),
+ }
+ }
+ return m
+}
+
+// ToUserIdentityMapping converts an [idtools.IdentityMapping] to a [user.IdentityMapping].
+//
+// Deprecated: use [user.IdentityMapping] directly, this is transitioning to user package.
+func ToUserIdentityMapping(u IdentityMapping) user.IdentityMapping {
+ return user.IdentityMapping{
+ UIDMaps: toUserIDMap(u.UIDMaps),
+ GIDMaps: toUserIDMap(u.GIDMaps),
+ }
+}
+
+func toUserIDMap(u []IDMap) []user.IDMap {
+ if u == nil {
+ return nil
+ }
+ m := make([]user.IDMap, len(u))
+ for i := range u {
+ m[i] = user.IDMap{
+ ID: int64(u[i].ContainerID),
+ ParentID: int64(u[i].HostID),
+ Count: int64(u[i].Size),
+ }
+ }
+ return m
+}
+
// RootPair returns a uid and gid pair for the root user. The error is ignored
// because a root user always exists, and the defaults are correct when the uid
// and gid maps are empty.
func (i IdentityMapping) RootPair() Identity {
- uid, gid, _ := GetRootUIDGID(i.UIDMaps, i.GIDMaps)
+ uid, gid, _ := getRootUIDGID(i.UIDMaps, i.GIDMaps)
return Identity{UID: uid, GID: gid}
}
@@ -144,6 +212,8 @@ func (i IdentityMapping) Empty() bool {
}
// CurrentIdentity returns the identity of the current process
+//
+// Deprecated: use [os.Getuid] and [os.Getegid] instead.
func CurrentIdentity() Identity {
return Identity{UID: os.Getuid(), GID: os.Getegid()}
}
diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go b/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go
index a12b140..f83f59f 100644
--- a/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go
+++ b/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go
@@ -1,9 +1,5 @@
package idtools
-import (
- "os"
-)
-
const (
SeTakeOwnershipPrivilege = "SeTakeOwnershipPrivilege"
)
@@ -14,11 +10,3 @@ const (
ContainerUserSidString = "S-1-5-93-2-2"
)
-
-// This is currently a wrapper around [os.MkdirAll] since currently
-// permissions aren't set through this path, the identity isn't utilized.
-// Ownership is handled elsewhere, but in the future could be support here
-// too.
-func mkdirAs(path string, _ os.FileMode, _ Identity, _, _ bool) error {
- return os.MkdirAll(path, 0)
-}
diff --git a/vendor/github.com/ebitengine/purego/dlfcn.go b/vendor/github.com/ebitengine/purego/dlfcn.go
index f70a245..cd1bf29 100644
--- a/vendor/github.com/ebitengine/purego/dlfcn.go
+++ b/vendor/github.com/ebitengine/purego/dlfcn.go
@@ -83,17 +83,17 @@ func loadSymbol(handle uintptr, name string) (uintptr, error) {
// appear to work if you link directly to the C function on darwin arm64.
//go:linkname dlopen dlopen
-var dlopen uintptr
+var dlopen uint8
var dlopenABI0 = uintptr(unsafe.Pointer(&dlopen))
//go:linkname dlsym dlsym
-var dlsym uintptr
+var dlsym uint8
var dlsymABI0 = uintptr(unsafe.Pointer(&dlsym))
//go:linkname dlclose dlclose
-var dlclose uintptr
+var dlclose uint8
var dlcloseABI0 = uintptr(unsafe.Pointer(&dlclose))
//go:linkname dlerror dlerror
-var dlerror uintptr
+var dlerror uint8
var dlerrorABI0 = uintptr(unsafe.Pointer(&dlerror))
diff --git a/vendor/github.com/ebitengine/purego/dlfcn_darwin.go b/vendor/github.com/ebitengine/purego/dlfcn_darwin.go
index 5f87627..27f5607 100644
--- a/vendor/github.com/ebitengine/purego/dlfcn_darwin.go
+++ b/vendor/github.com/ebitengine/purego/dlfcn_darwin.go
@@ -17,8 +17,3 @@ const (
//go:cgo_import_dynamic purego_dlsym dlsym "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic purego_dlerror dlerror "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic purego_dlclose dlclose "/usr/lib/libSystem.B.dylib"
-
-//go:cgo_import_dynamic purego_dlopen dlopen "/usr/lib/libSystem.B.dylib"
-//go:cgo_import_dynamic purego_dlsym dlsym "/usr/lib/libSystem.B.dylib"
-//go:cgo_import_dynamic purego_dlerror dlerror "/usr/lib/libSystem.B.dylib"
-//go:cgo_import_dynamic purego_dlclose dlclose "/usr/lib/libSystem.B.dylib"
diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go
index 7a3a1bb..d17942e 100644
--- a/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go
+++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go
@@ -121,81 +121,81 @@ func pthread_setspecific(key pthread_key_t, value unsafe.Pointer) int32 {
}
//go:linkname _malloc _malloc
-var _malloc uintptr
+var _malloc uint8
var mallocABI0 = uintptr(unsafe.Pointer(&_malloc))
//go:linkname _free _free
-var _free uintptr
+var _free uint8
var freeABI0 = uintptr(unsafe.Pointer(&_free))
//go:linkname _setenv _setenv
-var _setenv uintptr
+var _setenv uint8
var setenvABI0 = uintptr(unsafe.Pointer(&_setenv))
//go:linkname _unsetenv _unsetenv
-var _unsetenv uintptr
+var _unsetenv uint8
var unsetenvABI0 = uintptr(unsafe.Pointer(&_unsetenv))
//go:linkname _sigfillset _sigfillset
-var _sigfillset uintptr
+var _sigfillset uint8
var sigfillsetABI0 = uintptr(unsafe.Pointer(&_sigfillset))
//go:linkname _nanosleep _nanosleep
-var _nanosleep uintptr
+var _nanosleep uint8
var nanosleepABI0 = uintptr(unsafe.Pointer(&_nanosleep))
//go:linkname _abort _abort
-var _abort uintptr
+var _abort uint8
var abortABI0 = uintptr(unsafe.Pointer(&_abort))
//go:linkname _pthread_attr_init _pthread_attr_init
-var _pthread_attr_init uintptr
+var _pthread_attr_init uint8
var pthread_attr_initABI0 = uintptr(unsafe.Pointer(&_pthread_attr_init))
//go:linkname _pthread_create _pthread_create
-var _pthread_create uintptr
+var _pthread_create uint8
var pthread_createABI0 = uintptr(unsafe.Pointer(&_pthread_create))
//go:linkname _pthread_detach _pthread_detach
-var _pthread_detach uintptr
+var _pthread_detach uint8
var pthread_detachABI0 = uintptr(unsafe.Pointer(&_pthread_detach))
//go:linkname _pthread_sigmask _pthread_sigmask
-var _pthread_sigmask uintptr
+var _pthread_sigmask uint8
var pthread_sigmaskABI0 = uintptr(unsafe.Pointer(&_pthread_sigmask))
//go:linkname _pthread_self _pthread_self
-var _pthread_self uintptr
+var _pthread_self uint8
var pthread_selfABI0 = uintptr(unsafe.Pointer(&_pthread_self))
//go:linkname _pthread_get_stacksize_np _pthread_get_stacksize_np
-var _pthread_get_stacksize_np uintptr
+var _pthread_get_stacksize_np uint8
var pthread_get_stacksize_npABI0 = uintptr(unsafe.Pointer(&_pthread_get_stacksize_np))
//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
-var _pthread_attr_getstacksize uintptr
+var _pthread_attr_getstacksize uint8
var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
//go:linkname _pthread_attr_setstacksize _pthread_attr_setstacksize
-var _pthread_attr_setstacksize uintptr
+var _pthread_attr_setstacksize uint8
var pthread_attr_setstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_setstacksize))
//go:linkname _pthread_attr_destroy _pthread_attr_destroy
-var _pthread_attr_destroy uintptr
+var _pthread_attr_destroy uint8
var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
//go:linkname _pthread_mutex_lock _pthread_mutex_lock
-var _pthread_mutex_lock uintptr
+var _pthread_mutex_lock uint8
var pthread_mutex_lockABI0 = uintptr(unsafe.Pointer(&_pthread_mutex_lock))
//go:linkname _pthread_mutex_unlock _pthread_mutex_unlock
-var _pthread_mutex_unlock uintptr
+var _pthread_mutex_unlock uint8
var pthread_mutex_unlockABI0 = uintptr(unsafe.Pointer(&_pthread_mutex_unlock))
//go:linkname _pthread_cond_broadcast _pthread_cond_broadcast
-var _pthread_cond_broadcast uintptr
+var _pthread_cond_broadcast uint8
var pthread_cond_broadcastABI0 = uintptr(unsafe.Pointer(&_pthread_cond_broadcast))
//go:linkname _pthread_setspecific _pthread_setspecific
-var _pthread_setspecific uintptr
+var _pthread_setspecific uint8
var pthread_setspecificABI0 = uintptr(unsafe.Pointer(&_pthread_setspecific))
diff --git a/vendor/github.com/go-ole/go-ole/SECURITY.md b/vendor/github.com/go-ole/go-ole/SECURITY.md
new file mode 100644
index 0000000..dac2815
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/SECURITY.md
@@ -0,0 +1,13 @@
+# Security Policy
+
+## Supported Versions
+
+Security updates are applied only to the latest release.
+
+## Reporting a Vulnerability
+
+If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
+
+Please disclose it at [security advisory](https://github.com/go-ole/go-ole/security/advisories/new).
+
+This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure.
diff --git a/vendor/github.com/go-ole/go-ole/appveyor.yml b/vendor/github.com/go-ole/go-ole/appveyor.yml
index 0d557ac..8df7fa2 100644
--- a/vendor/github.com/go-ole/go-ole/appveyor.yml
+++ b/vendor/github.com/go-ole/go-ole/appveyor.yml
@@ -6,14 +6,9 @@
version: "1.3.0.{build}-alpha-{branch}"
-os: Windows Server 2012 R2
+os: Visual Studio 2019
-branches:
- only:
- - master
- - v1.2
- - v1.1
- - v1.0
+build: off
skip_tags: true
@@ -21,20 +16,40 @@ clone_folder: c:\gopath\src\github.com\go-ole\go-ole
environment:
GOPATH: c:\gopath
- matrix:
- - GOARCH: amd64
- GOVERSION: 1.5
- GOROOT: c:\go
- DOWNLOADPLATFORM: "x64"
+ GOROOT: c:\go
+ DOWNLOADPLATFORM: "x64"
-install:
- - choco install mingw
- - SET PATH=c:\tools\mingw64\bin;%PATH%
+before_test:
# - Download COM Server
- ps: Start-FileDownload "https://github.com/go-ole/test-com-server/releases/download/v1.0.2/test-com-server-${env:DOWNLOADPLATFORM}.zip"
- 7z e test-com-server-%DOWNLOADPLATFORM%.zip -oc:\gopath\src\github.com\go-ole\go-ole > NUL
- c:\gopath\src\github.com\go-ole\go-ole\build\register-assembly.bat
- # - set
+
+test_script:
+ - go test -v -cover ./...
+ # go vet has false positives on unsafe.Pointer with windows/sys. Disabling since it is recommended to use go test instead.
+ # - go vet ./...
+
+branches:
+ only:
+ - master
+ - v1.2
+ - v1.1
+ - v1.0
+
+matrix:
+ allow_failures:
+ - environment:
+ GOROOT: C:\go-x86
+ DOWNLOADPLATFORM: "x86"
+ - environment:
+ GOROOT: C:\go118
+ DOWNLOADPLATFORM: "x64"
+ - environment:
+ GOROOT: C:\go118-x86
+ DOWNLOADPLATFORM: "x86"
+
+install:
- go version
- go env
- go get -u golang.org/x/tools/cmd/cover
@@ -45,10 +60,9 @@ build_script:
- cd c:\gopath\src\github.com\go-ole\go-ole
- go get -v -t ./...
- go build
- - go test -v -cover ./...
# disable automatic tests
-test: off
+test: on
# disable deployment
deploy: off
diff --git a/vendor/github.com/go-ole/go-ole/com.go b/vendor/github.com/go-ole/go-ole/com.go
index a9bef15..cabbac0 100644
--- a/vendor/github.com/go-ole/go-ole/com.go
+++ b/vendor/github.com/go-ole/go-ole/com.go
@@ -11,6 +11,7 @@ import (
var (
procCoInitialize = modole32.NewProc("CoInitialize")
procCoInitializeEx = modole32.NewProc("CoInitializeEx")
+ procCoInitializeSecurity = modole32.NewProc("CoInitializeSecurity")
procCoUninitialize = modole32.NewProc("CoUninitialize")
procCoCreateInstance = modole32.NewProc("CoCreateInstance")
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
@@ -37,6 +38,9 @@ var (
procDispatchMessageW = moduser32.NewProc("DispatchMessageW")
)
+// This is to enable calling COM Security initialization multiple times
+var bSecurityInit bool = false
+
// coInitialize initializes COM library on current thread.
//
// MSDN documentation suggests that this function should not be called. Call
@@ -68,6 +72,35 @@ func coInitializeEx(coinit uint32) (err error) {
return
}
+// coInitializeSecurity: Registers security and sets the default security values
+// for the process.
+func coInitializeSecurity(cAuthSvc int32,
+ dwAuthnLevel uint32,
+ dwImpLevel uint32,
+ dwCapabilities uint32) (err error) {
+ // Check COM Security initialization has done previously
+ if !bSecurityInit {
+ // https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-coinitializesecurity
+ hr, _, _ := procCoInitializeSecurity.Call(
+ uintptr(0), // Allow *all* VSS writers to communicate back!
+ uintptr(cAuthSvc), // Default COM authentication service
+ uintptr(0), // Default COM authorization service
+ uintptr(0), // Reserved parameter
+ uintptr(dwAuthnLevel), // Strongest COM authentication level
+ uintptr(dwImpLevel), // Minimal impersonation abilities
+ uintptr(0), // Default COM authentication settings
+ uintptr(dwCapabilities), // Cloaking
+ uintptr(0)) // eserved parameter
+ if hr != 0 {
+ err = NewError(hr)
+ } else {
+ // COM Security initialization done make global flag true.
+ bSecurityInit = true
+ }
+ }
+ return
+}
+
// CoInitialize initializes COM library on current thread.
//
// MSDN documentation suggests that this function should not be called. Call
@@ -96,6 +129,15 @@ func CoUninitialize() {
procCoUninitialize.Call()
}
+// CoInitializeSecurity: Registers security and sets the default security values
+// for the process.
+func CoInitializeSecurity(cAuthSvc int32,
+ dwAuthnLevel uint32,
+ dwImpLevel uint32,
+ dwCapabilities uint32) (err error) {
+ return coInitializeSecurity(cAuthSvc, dwAuthnLevel, dwImpLevel, dwCapabilities)
+}
+
// CoTaskMemFree frees memory pointer.
func CoTaskMemFree(memptr uintptr) {
procCoTaskMemFree.Call(memptr)
diff --git a/vendor/github.com/go-ole/go-ole/idispatch_windows.go b/vendor/github.com/go-ole/go-ole/idispatch_windows.go
index b399f04..649c073 100644
--- a/vendor/github.com/go-ole/go-ole/idispatch_windows.go
+++ b/vendor/github.com/go-ole/go-ole/idispatch_windows.go
@@ -1,3 +1,4 @@
+//go:build windows
// +build windows
package ole
@@ -92,7 +93,7 @@ func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}
case int8:
vargs[n] = NewVariant(VT_I1, int64(v.(int8)))
case *int8:
- vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8)))))
+ vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int8)))))
case int16:
vargs[n] = NewVariant(VT_I2, int64(v.(int16)))
case *int16:
diff --git a/vendor/github.com/go-ole/go-ole/variant.go b/vendor/github.com/go-ole/go-ole/variant.go
index 967a23f..a2c8402 100644
--- a/vendor/github.com/go-ole/go-ole/variant.go
+++ b/vendor/github.com/go-ole/go-ole/variant.go
@@ -99,7 +99,7 @@ func (v *VARIANT) Value() interface{} {
case VT_DISPATCH:
return v.ToIDispatch()
case VT_BOOL:
- return v.Val != 0
+ return (v.Val & 0xffff) != 0
}
return nil
}
diff --git a/vendor/github.com/go-stack/stack/LICENSE.md b/vendor/github.com/go-stack/stack/LICENSE.md
new file mode 100644
index 0000000..2abf98e
--- /dev/null
+++ b/vendor/github.com/go-stack/stack/LICENSE.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Chris Hines
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/go-stack/stack/README.md b/vendor/github.com/go-stack/stack/README.md
new file mode 100644
index 0000000..f11cccc
--- /dev/null
+++ b/vendor/github.com/go-stack/stack/README.md
@@ -0,0 +1,38 @@
+[![GoDoc](https://godoc.org/github.com/go-stack/stack?status.svg)](https://godoc.org/github.com/go-stack/stack)
+[![Go Report Card](https://goreportcard.com/badge/go-stack/stack)](https://goreportcard.com/report/go-stack/stack)
+[![TravisCI](https://travis-ci.org/go-stack/stack.svg?branch=master)](https://travis-ci.org/go-stack/stack)
+[![Coverage Status](https://coveralls.io/repos/github/go-stack/stack/badge.svg?branch=master)](https://coveralls.io/github/go-stack/stack?branch=master)
+
+# stack
+
+Package stack implements utilities to capture, manipulate, and format call
+stacks. It provides a simpler API than package runtime.
+
+The implementation takes care of the minutia and special cases of interpreting
+the program counter (pc) values returned by runtime.Callers.
+
+## Versioning
+
+Package stack publishes releases via [semver](http://semver.org/) compatible Git
+tags prefixed with a single 'v'. The master branch always contains the latest
+release. The develop branch contains unreleased commits.
+
+## Formatting
+
+Package stack's types implement fmt.Formatter, which provides a simple and
+flexible way to declaratively configure formatting when used with logging or
+error tracking packages.
+
+```go
+func DoTheThing() {
+ c := stack.Caller(0)
+ log.Print(c) // "source.go:10"
+ log.Printf("%+v", c) // "pkg/path/source.go:10"
+ log.Printf("%n", c) // "DoTheThing"
+
+ s := stack.Trace().TrimRuntime()
+ log.Print(s) // "[source.go:15 caller.go:42 main.go:14]"
+}
+```
+
+See the docs for all of the supported formatting options.
diff --git a/vendor/github.com/go-stack/stack/stack.go b/vendor/github.com/go-stack/stack/stack.go
new file mode 100644
index 0000000..ac3b93b
--- /dev/null
+++ b/vendor/github.com/go-stack/stack/stack.go
@@ -0,0 +1,400 @@
+// +build go1.7
+
+// Package stack implements utilities to capture, manipulate, and format call
+// stacks. It provides a simpler API than package runtime.
+//
+// The implementation takes care of the minutia and special cases of
+// interpreting the program counter (pc) values returned by runtime.Callers.
+//
+// Package stack's types implement fmt.Formatter, which provides a simple and
+// flexible way to declaratively configure formatting when used with logging
+// or error tracking packages.
+package stack
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "runtime"
+ "strconv"
+ "strings"
+)
+
+// Call records a single function invocation from a goroutine stack.
+type Call struct {
+ frame runtime.Frame
+}
+
+// Caller returns a Call from the stack of the current goroutine. The argument
+// skip is the number of stack frames to ascend, with 0 identifying the
+// calling function.
+func Caller(skip int) Call {
+ // As of Go 1.9 we need room for up to three PC entries.
+ //
+ // 0. An entry for the stack frame prior to the target to check for
+ // special handling needed if that prior entry is runtime.sigpanic.
+ // 1. A possible second entry to hold metadata about skipped inlined
+ // functions. If inline functions were not skipped the target frame
+ // PC will be here.
+ // 2. A third entry for the target frame PC when the second entry
+ // is used for skipped inline functions.
+ var pcs [3]uintptr
+ n := runtime.Callers(skip+1, pcs[:])
+ frames := runtime.CallersFrames(pcs[:n])
+ frame, _ := frames.Next()
+ frame, _ = frames.Next()
+
+ return Call{
+ frame: frame,
+ }
+}
+
+// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", c).
+func (c Call) String() string {
+ return fmt.Sprint(c)
+}
+
+// MarshalText implements encoding.TextMarshaler. It formats the Call the same
+// as fmt.Sprintf("%v", c).
+func (c Call) MarshalText() ([]byte, error) {
+ if c.frame == (runtime.Frame{}) {
+ return nil, ErrNoFunc
+ }
+
+ buf := bytes.Buffer{}
+ fmt.Fprint(&buf, c)
+ return buf.Bytes(), nil
+}
+
+// ErrNoFunc means that the Call has a nil *runtime.Func. The most likely
+// cause is a Call with the zero value.
+var ErrNoFunc = errors.New("no call stack information")
+
+// Format implements fmt.Formatter with support for the following verbs.
+//
+// %s source file
+// %d line number
+// %n function name
+// %k last segment of the package path
+// %v equivalent to %s:%d
+//
+// It accepts the '+' and '#' flags for most of the verbs as follows.
+//
+// %+s path of source file relative to the compile time GOPATH,
+// or the module path joined to the path of source file relative
+// to module root
+// %#s full path of source file
+// %+n import path qualified function name
+// %+k full package path
+// %+v equivalent to %+s:%d
+// %#v equivalent to %#s:%d
+func (c Call) Format(s fmt.State, verb rune) {
+ if c.frame == (runtime.Frame{}) {
+ fmt.Fprintf(s, "%%!%c(NOFUNC)", verb)
+ return
+ }
+
+ switch verb {
+ case 's', 'v':
+ file := c.frame.File
+ switch {
+ case s.Flag('#'):
+ // done
+ case s.Flag('+'):
+ file = pkgFilePath(&c.frame)
+ default:
+ const sep = "/"
+ if i := strings.LastIndex(file, sep); i != -1 {
+ file = file[i+len(sep):]
+ }
+ }
+ io.WriteString(s, file)
+ if verb == 'v' {
+ buf := [7]byte{':'}
+ s.Write(strconv.AppendInt(buf[:1], int64(c.frame.Line), 10))
+ }
+
+ case 'd':
+ buf := [6]byte{}
+ s.Write(strconv.AppendInt(buf[:0], int64(c.frame.Line), 10))
+
+ case 'k':
+ name := c.frame.Function
+ const pathSep = "/"
+ start, end := 0, len(name)
+ if i := strings.LastIndex(name, pathSep); i != -1 {
+ start = i + len(pathSep)
+ }
+ const pkgSep = "."
+ if i := strings.Index(name[start:], pkgSep); i != -1 {
+ end = start + i
+ }
+ if s.Flag('+') {
+ start = 0
+ }
+ io.WriteString(s, name[start:end])
+
+ case 'n':
+ name := c.frame.Function
+ if !s.Flag('+') {
+ const pathSep = "/"
+ if i := strings.LastIndex(name, pathSep); i != -1 {
+ name = name[i+len(pathSep):]
+ }
+ const pkgSep = "."
+ if i := strings.Index(name, pkgSep); i != -1 {
+ name = name[i+len(pkgSep):]
+ }
+ }
+ io.WriteString(s, name)
+ }
+}
+
+// Frame returns the call frame infomation for the Call.
+func (c Call) Frame() runtime.Frame {
+ return c.frame
+}
+
+// PC returns the program counter for this call frame; multiple frames may
+// have the same PC value.
+//
+// Deprecated: Use Call.Frame instead.
+func (c Call) PC() uintptr {
+ return c.frame.PC
+}
+
+// CallStack records a sequence of function invocations from a goroutine
+// stack.
+type CallStack []Call
+
+// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", cs).
+func (cs CallStack) String() string {
+ return fmt.Sprint(cs)
+}
+
+var (
+ openBracketBytes = []byte("[")
+ closeBracketBytes = []byte("]")
+ spaceBytes = []byte(" ")
+)
+
+// MarshalText implements encoding.TextMarshaler. It formats the CallStack the
+// same as fmt.Sprintf("%v", cs).
+func (cs CallStack) MarshalText() ([]byte, error) {
+ buf := bytes.Buffer{}
+ buf.Write(openBracketBytes)
+ for i, pc := range cs {
+ if i > 0 {
+ buf.Write(spaceBytes)
+ }
+ fmt.Fprint(&buf, pc)
+ }
+ buf.Write(closeBracketBytes)
+ return buf.Bytes(), nil
+}
+
+// Format implements fmt.Formatter by printing the CallStack as square brackets
+// ([, ]) surrounding a space separated list of Calls each formatted with the
+// supplied verb and options.
+func (cs CallStack) Format(s fmt.State, verb rune) {
+ s.Write(openBracketBytes)
+ for i, pc := range cs {
+ if i > 0 {
+ s.Write(spaceBytes)
+ }
+ pc.Format(s, verb)
+ }
+ s.Write(closeBracketBytes)
+}
+
+// Trace returns a CallStack for the current goroutine with element 0
+// identifying the calling function.
+func Trace() CallStack {
+ var pcs [512]uintptr
+ n := runtime.Callers(1, pcs[:])
+
+ frames := runtime.CallersFrames(pcs[:n])
+ cs := make(CallStack, 0, n)
+
+ // Skip extra frame retrieved just to make sure the runtime.sigpanic
+ // special case is handled.
+ frame, more := frames.Next()
+
+ for more {
+ frame, more = frames.Next()
+ cs = append(cs, Call{frame: frame})
+ }
+
+ return cs
+}
+
+// TrimBelow returns a slice of the CallStack with all entries below c
+// removed.
+func (cs CallStack) TrimBelow(c Call) CallStack {
+ for len(cs) > 0 && cs[0] != c {
+ cs = cs[1:]
+ }
+ return cs
+}
+
+// TrimAbove returns a slice of the CallStack with all entries above c
+// removed.
+func (cs CallStack) TrimAbove(c Call) CallStack {
+ for len(cs) > 0 && cs[len(cs)-1] != c {
+ cs = cs[:len(cs)-1]
+ }
+ return cs
+}
+
+// pkgIndex returns the index that results in file[index:] being the path of
+// file relative to the compile time GOPATH, and file[:index] being the
+// $GOPATH/src/ portion of file. funcName must be the name of a function in
+// file as returned by runtime.Func.Name.
+func pkgIndex(file, funcName string) int {
+ // As of Go 1.6.2 there is no direct way to know the compile time GOPATH
+ // at runtime, but we can infer the number of path segments in the GOPATH.
+ // We note that runtime.Func.Name() returns the function name qualified by
+ // the import path, which does not include the GOPATH. Thus we can trim
+ // segments from the beginning of the file path until the number of path
+ // separators remaining is one more than the number of path separators in
+ // the function name. For example, given:
+ //
+ // GOPATH /home/user
+ // file /home/user/src/pkg/sub/file.go
+ // fn.Name() pkg/sub.Type.Method
+ //
+ // We want to produce:
+ //
+ // file[:idx] == /home/user/src/
+ // file[idx:] == pkg/sub/file.go
+ //
+ // From this we can easily see that fn.Name() has one less path separator
+ // than our desired result for file[idx:]. We count separators from the
+ // end of the file path until it finds two more than in the function name
+ // and then move one character forward to preserve the initial path
+ // segment without a leading separator.
+ const sep = "/"
+ i := len(file)
+ for n := strings.Count(funcName, sep) + 2; n > 0; n-- {
+ i = strings.LastIndex(file[:i], sep)
+ if i == -1 {
+ i = -len(sep)
+ break
+ }
+ }
+ // get back to 0 or trim the leading separator
+ return i + len(sep)
+}
+
+// pkgFilePath returns the frame's filepath relative to the compile-time GOPATH,
+// or its module path joined to its path relative to the module root.
+//
+// As of Go 1.11 there is no direct way to know the compile time GOPATH or
+// module paths at runtime, but we can piece together the desired information
+// from available information. We note that runtime.Frame.Function contains the
+// function name qualified by the package path, which includes the module path
+// but not the GOPATH. We can extract the package path from that and append the
+// last segments of the file path to arrive at the desired package qualified
+// file path. For example, given:
+//
+// GOPATH /home/user
+// import path pkg/sub
+// frame.File /home/user/src/pkg/sub/file.go
+// frame.Function pkg/sub.Type.Method
+// Desired return pkg/sub/file.go
+//
+// It appears that we simply need to trim ".Type.Method" from frame.Function and
+// append "/" + path.Base(file).
+//
+// But there are other wrinkles. Although it is idiomatic to do so, the internal
+// name of a package is not required to match the last segment of its import
+// path. In addition, the introduction of modules in Go 1.11 allows working
+// without a GOPATH. So we also must make these work right:
+//
+// GOPATH /home/user
+// import path pkg/go-sub
+// package name sub
+// frame.File /home/user/src/pkg/go-sub/file.go
+// frame.Function pkg/sub.Type.Method
+// Desired return pkg/go-sub/file.go
+//
+// Module path pkg/v2
+// import path pkg/v2/go-sub
+// package name sub
+// frame.File /home/user/cloned-pkg/go-sub/file.go
+// frame.Function pkg/v2/sub.Type.Method
+// Desired return pkg/v2/go-sub/file.go
+//
+// We can handle all of these situations by using the package path extracted
+// from frame.Function up to, but not including, the last segment as the prefix
+// and the last two segments of frame.File as the suffix of the returned path.
+// This preserves the existing behavior when working in a GOPATH without modules
+// and a semantically equivalent behavior when used in module aware project.
+func pkgFilePath(frame *runtime.Frame) string {
+ pre := pkgPrefix(frame.Function)
+ post := pathSuffix(frame.File)
+ if pre == "" {
+ return post
+ }
+ return pre + "/" + post
+}
+
+// pkgPrefix returns the import path of the function's package with the final
+// segment removed.
+func pkgPrefix(funcName string) string {
+ const pathSep = "/"
+ end := strings.LastIndex(funcName, pathSep)
+ if end == -1 {
+ return ""
+ }
+ return funcName[:end]
+}
+
+// pathSuffix returns the last two segments of path.
+func pathSuffix(path string) string {
+ const pathSep = "/"
+ lastSep := strings.LastIndex(path, pathSep)
+ if lastSep == -1 {
+ return path
+ }
+ return path[strings.LastIndex(path[:lastSep], pathSep)+1:]
+}
+
+var runtimePath string
+
+func init() {
+ var pcs [3]uintptr
+ runtime.Callers(0, pcs[:])
+ frames := runtime.CallersFrames(pcs[:])
+ frame, _ := frames.Next()
+ file := frame.File
+
+ idx := pkgIndex(frame.File, frame.Function)
+
+ runtimePath = file[:idx]
+ if runtime.GOOS == "windows" {
+ runtimePath = strings.ToLower(runtimePath)
+ }
+}
+
+func inGoroot(c Call) bool {
+ file := c.frame.File
+ if len(file) == 0 || file[0] == '?' {
+ return true
+ }
+ if runtime.GOOS == "windows" {
+ file = strings.ToLower(file)
+ }
+ return strings.HasPrefix(file, runtimePath) || strings.HasSuffix(file, "/_testmain.go")
+}
+
+// TrimRuntime returns a slice of the CallStack with the topmost entries from
+// the go runtime removed. It considers any calls originating from unknown
+// files, files under GOROOT, or _testmain.go as part of the runtime.
+func (cs CallStack) TrimRuntime() CallStack {
+ for len(cs) > 0 && inGoroot(cs[len(cs)-1]) {
+ cs = cs[:len(cs)-1]
+ }
+ return cs
+}
diff --git a/vendor/github.com/lufia/plan9stats/README.md b/vendor/github.com/lufia/plan9stats/README.md
index a21700c..70e5386 100644
--- a/vendor/github.com/lufia/plan9stats/README.md
+++ b/vendor/github.com/lufia/plan9stats/README.md
@@ -1,2 +1,10 @@
# plan9stats
A module for retrieving statistics of Plan 9
+
+[![GoDev][godev-image]][godev-url]
+[![Actions Status][actions-image]][actions-url]
+
+[godev-image]: https://pkg.go.dev/badge/github.com/lufia/plan9stats
+[godev-url]: https://pkg.go.dev/github.com/lufia/plan9stats
+[actions-image]: https://github.com/lufia/plan9stats/workflows/Test/badge.svg?branch=main
+[actions-url]: https://github.com/lufia/plan9stats/actions?workflow=Test
diff --git a/vendor/github.com/lufia/plan9stats/cpu.go b/vendor/github.com/lufia/plan9stats/cpu.go
index a101b91..eaff362 100644
--- a/vendor/github.com/lufia/plan9stats/cpu.go
+++ b/vendor/github.com/lufia/plan9stats/cpu.go
@@ -178,9 +178,12 @@ func ReadCPUStats(ctx context.Context, opts ...Option) (*CPUStats, error) {
var up uint32parser
pids := make([]uint32, len(names))
for i, s := range names {
+ if s == "trace" {
+ continue
+ }
pids[i] = up.Parse(s)
}
- if up.err != nil {
+ if err := up.err; err != nil {
return nil, err
}
sort.Slice(pids, func(i, j int) bool {
diff --git a/vendor/github.com/lufia/plan9stats/disk.go b/vendor/github.com/lufia/plan9stats/disk.go
new file mode 100644
index 0000000..4a4fa0c
--- /dev/null
+++ b/vendor/github.com/lufia/plan9stats/disk.go
@@ -0,0 +1,116 @@
+package stats
+
+import (
+ "bufio"
+ "bytes"
+ "context"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+// Storage represents /dev/sdXX/ctl.
+type Storage struct {
+ Name string
+ Model string
+ Capacity int64
+ Partitions []*Partition
+}
+
+// Partition represents a part of /dev/sdXX/ctl.
+type Partition struct {
+ Name string
+ Start uint64
+ End uint64
+}
+
+func ReadStorages(ctx context.Context, opts ...Option) ([]*Storage, error) {
+ cfg := newConfig(opts...)
+ sdctl := filepath.Join(cfg.rootdir, "/dev/sdctl")
+ f, err := os.Open(sdctl)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ var a []*Storage
+ scanner := bufio.NewScanner(f)
+ for scanner.Scan() {
+ fields := bytes.Split(scanner.Bytes(), delim)
+ if len(fields) == 0 {
+ continue
+ }
+ exp := string(fields[0]) + "*"
+ if !strings.HasPrefix(exp, "sd") {
+ continue
+ }
+ dir := filepath.Join(cfg.rootdir, "/dev", exp)
+ m, err := filepath.Glob(dir)
+ if err != nil {
+ return nil, err
+ }
+ for _, dir := range m {
+ s, err := readStorage(dir)
+ if err != nil {
+ return nil, err
+ }
+ a = append(a, s)
+ }
+ }
+ if err := scanner.Err(); err != nil {
+ return nil, err
+ }
+ return a, nil
+}
+
+func readStorage(dir string) (*Storage, error) {
+ ctl := filepath.Join(dir, "ctl")
+ f, err := os.Open(ctl)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ var s Storage
+ s.Name = filepath.Base(dir)
+ scanner := bufio.NewScanner(f)
+ for scanner.Scan() {
+ line := scanner.Bytes()
+ switch {
+ case bytes.HasPrefix(line, []byte("inquiry ")):
+ s.Model = string(bytes.TrimSpace(line[7:]))
+ case bytes.HasPrefix(line, []byte("geometry ")):
+ fields := bytes.Split(line, delim)
+ if len(fields) < 3 {
+ continue
+ }
+ var p intParser
+ sec := p.ParseInt64(string(fields[1]), 10)
+ size := p.ParseInt64(string(fields[2]), 10)
+ if err := p.Err(); err != nil {
+ return nil, err
+ }
+ s.Capacity = sec * size
+ case bytes.HasPrefix(line, []byte("part ")):
+ fields := bytes.Split(line, delim)
+ if len(fields) < 4 {
+ continue
+ }
+ var p intParser
+ start := p.ParseUint64(string(fields[2]), 10)
+ end := p.ParseUint64(string(fields[3]), 10)
+ if err := p.Err(); err != nil {
+ return nil, err
+ }
+ s.Partitions = append(s.Partitions, &Partition{
+ Name: string(fields[1]),
+ Start: start,
+ End: end,
+ })
+ }
+ }
+ if err := scanner.Err(); err != nil {
+ return nil, err
+ }
+ return &s, nil
+}
diff --git a/vendor/github.com/lufia/plan9stats/host.go b/vendor/github.com/lufia/plan9stats/host.go
index 957e903..a3921c0 100644
--- a/vendor/github.com/lufia/plan9stats/host.go
+++ b/vendor/github.com/lufia/plan9stats/host.go
@@ -109,12 +109,6 @@ func parseGauge(s string, r *Gauge) error {
return nil
}
-type Storage struct {
- Name string
- Model string
- Capacity int64
-}
-
type Interface struct {
Name string
Addr string
@@ -177,7 +171,7 @@ func ReadHost(ctx context.Context, opts ...Option) (*Host, error) {
}
h.Sysname = name
- a, err := readStorages(cfg.rootdir)
+ a, err := ReadStorages(ctx, opts...)
if err != nil {
return nil, err
}
@@ -203,80 +197,6 @@ func readSysname(rootdir string) (string, error) {
return string(bytes.TrimSpace(b)), nil
}
-func readStorages(rootdir string) ([]*Storage, error) {
- sdctl := filepath.Join(rootdir, "/dev/sdctl")
- f, err := os.Open(sdctl)
- if err != nil {
- return nil, err
- }
- defer f.Close()
-
- var a []*Storage
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- fields := bytes.Split(scanner.Bytes(), delim)
- if len(fields) == 0 {
- continue
- }
- exp := string(fields[0]) + "*"
- if !strings.HasPrefix(exp, "sd") {
- continue
- }
- dir := filepath.Join(rootdir, "/dev", exp)
- m, err := filepath.Glob(dir)
- if err != nil {
- return nil, err
- }
- for _, dir := range m {
- s, err := readStorage(dir)
- if err != nil {
- return nil, err
- }
- a = append(a, s)
- }
- }
- if err := scanner.Err(); err != nil {
- return nil, err
- }
- return a, nil
-}
-
-func readStorage(dir string) (*Storage, error) {
- ctl := filepath.Join(dir, "ctl")
- f, err := os.Open(ctl)
- if err != nil {
- return nil, err
- }
- defer f.Close()
-
- var s Storage
- s.Name = filepath.Base(dir)
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- line := scanner.Bytes()
- switch {
- case bytes.HasPrefix(line, []byte("inquiry")):
- s.Model = string(bytes.TrimSpace(line[7:]))
- case bytes.HasPrefix(line, []byte("geometry")):
- fields := bytes.Split(line, delim)
- if len(fields) < 3 {
- continue
- }
- var p intParser
- sec := p.ParseInt64(string(fields[1]), 10)
- size := p.ParseInt64(string(fields[2]), 10)
- if err := p.Err(); err != nil {
- return nil, err
- }
- s.Capacity = sec * size
- }
- }
- if err := scanner.Err(); err != nil {
- return nil, err
- }
- return &s, nil
-}
-
type IPStats struct {
ID int // number of interface in ipifc dir
Device string // associated physical device
diff --git a/vendor/github.com/lufia/plan9stats/int.go b/vendor/github.com/lufia/plan9stats/int.go
index db133c4..e3c9dc8 100644
--- a/vendor/github.com/lufia/plan9stats/int.go
+++ b/vendor/github.com/lufia/plan9stats/int.go
@@ -26,6 +26,15 @@ func (p *intParser) ParseInt64(s string, base int) int64 {
return n
}
+func (p *intParser) ParseUint64(s string, base int) uint64 {
+ if p.err != nil {
+ return 0
+ }
+ var n uint64
+ n, p.err = strconv.ParseUint(s, base, 64)
+ return n
+}
+
func (p *intParser) Err() error {
return p.err
}
diff --git a/vendor/github.com/moby/go-archive/.gitattributes b/vendor/github.com/moby/go-archive/.gitattributes
new file mode 100644
index 0000000..4bb139d
--- /dev/null
+++ b/vendor/github.com/moby/go-archive/.gitattributes
@@ -0,0 +1,2 @@
+*.go -text diff=golang
+*.go text eol=lf
diff --git a/vendor/github.com/moby/go-archive/.gitignore b/vendor/github.com/moby/go-archive/.gitignore
new file mode 100644
index 0000000..3f2bc47
--- /dev/null
+++ b/vendor/github.com/moby/go-archive/.gitignore
@@ -0,0 +1 @@
+/coverage.txt
diff --git a/vendor/github.com/moby/go-archive/.golangci.yml b/vendor/github.com/moby/go-archive/.golangci.yml
new file mode 100644
index 0000000..21439e5
--- /dev/null
+++ b/vendor/github.com/moby/go-archive/.golangci.yml
@@ -0,0 +1,33 @@
+version: "2"
+
+issues:
+ # Disable maximum issues count per one linter.
+ max-issues-per-linter: 0
+ # Disable maximum count of issues with the same text.
+ max-same-issues: 0
+
+linters:
+ enable:
+ - errorlint
+ - unconvert
+ - unparam
+ exclusions:
+ generated: disable
+ presets:
+ - comments
+ - std-error-handling
+ settings:
+ staticcheck:
+ # Enable all options, with some exceptions.
+ # For defaults, see https://golangci-lint.run/usage/linters/#staticcheck
+ checks:
+ - all
+ - -QF1008 # Omit embedded fields from selector expression; https://staticcheck.dev/docs/checks/#QF1008
+ - -ST1003 # Poorly chosen identifier; https://staticcheck.dev/docs/checks/#ST1003
+
+formatters:
+ enable:
+ - gofumpt
+ - goimports
+ exclusions:
+ generated: disable
diff --git a/vendor/github.com/moby/go-archive/LICENSE b/vendor/github.com/moby/go-archive/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/vendor/github.com/moby/go-archive/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/docker/docker/pkg/archive/archive.go b/vendor/github.com/moby/go-archive/archive.go
index 9bbb11c..7a105ae 100644
--- a/vendor/github.com/docker/docker/pkg/archive/archive.go
+++ b/vendor/github.com/moby/go-archive/archive.go
@@ -3,32 +3,24 @@ package archive
import (
"archive/tar"
- "bufio"
- "bytes"
- "compress/bzip2"
- "compress/gzip"
"context"
- "encoding/binary"
"errors"
"fmt"
"io"
"os"
- "os/exec"
"path/filepath"
"runtime"
- "runtime/debug"
- "strconv"
"strings"
- "sync"
- "sync/atomic"
"syscall"
"time"
"github.com/containerd/log"
- "github.com/docker/docker/pkg/idtools"
- "github.com/klauspost/compress/zstd"
"github.com/moby/patternmatcher"
"github.com/moby/sys/sequential"
+ "github.com/moby/sys/user"
+
+ "github.com/moby/go-archive/compression"
+ "github.com/moby/go-archive/tarheader"
)
// ImpliedDirectoryMode represents the mode (Unix permissions) applied to directories that are implied by files in a
@@ -45,18 +37,25 @@ const ImpliedDirectoryMode = 0o755
type (
// Compression is the state represents if compressed or not.
- Compression int
+ //
+ // Deprecated: use [compression.Compression].
+ Compression = compression.Compression
// WhiteoutFormat is the format of whiteouts unpacked
WhiteoutFormat int
+ ChownOpts struct {
+ UID int
+ GID int
+ }
+
// TarOptions wraps the tar options.
TarOptions struct {
IncludeFiles []string
ExcludePatterns []string
- Compression Compression
+ Compression compression.Compression
NoLchown bool
- IDMap idtools.IdentityMapping
- ChownOpts *idtools.Identity
+ IDMap user.IdentityMapping
+ ChownOpts *ChownOpts
IncludeSourceDir bool
// WhiteoutFormat is the expected on disk format for whiteout files.
// This format will be converted to the standard format on pack
@@ -83,7 +82,7 @@ type (
// mappings for untar, an Archiver can be created with maps which will then be passed to Untar operations.
type Archiver struct {
Untar func(io.Reader, string, *TarOptions) error
- IDMapping idtools.IdentityMapping
+ IDMapping user.IdentityMapping
}
// NewDefaultArchiver returns a new Archiver without any IdentityMapping
@@ -97,11 +96,11 @@ func NewDefaultArchiver() *Archiver {
type breakoutError error
const (
- Uncompressed Compression = 0 // Uncompressed represents the uncompressed.
- Bzip2 Compression = 1 // Bzip2 is bzip2 compression algorithm.
- Gzip Compression = 2 // Gzip is gzip compression algorithm.
- Xz Compression = 3 // Xz is xz compression algorithm.
- Zstd Compression = 4 // Zstd is zstd compression algorithm.
+ Uncompressed = compression.None // Deprecated: use [compression.None].
+ Bzip2 = compression.Bzip2 // Deprecated: use [compression.Bzip2].
+ Gzip = compression.Gzip // Deprecated: use [compression.Gzip].
+ Xz = compression.Xz // Deprecated: use [compression.Xz].
+ Zstd = compression.Zstd // Deprecated: use [compression.Zstd].
)
const (
@@ -117,7 +116,7 @@ func IsArchivePath(path string) bool {
return false
}
defer file.Close()
- rdr, err := DecompressStream(file)
+ rdr, err := compression.DecompressStream(file)
if err != nil {
return false
}
@@ -127,242 +126,25 @@ func IsArchivePath(path string) bool {
return err == nil
}
-const (
- zstdMagicSkippableStart = 0x184D2A50
- zstdMagicSkippableMask = 0xFFFFFFF0
-)
-
-var (
- bzip2Magic = []byte{0x42, 0x5A, 0x68}
- gzipMagic = []byte{0x1F, 0x8B, 0x08}
- xzMagic = []byte{0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}
- zstdMagic = []byte{0x28, 0xb5, 0x2f, 0xfd}
-)
-
-type matcher = func([]byte) bool
-
-func magicNumberMatcher(m []byte) matcher {
- return func(source []byte) bool {
- return bytes.HasPrefix(source, m)
- }
-}
-
-// zstdMatcher detects zstd compression algorithm.
-// Zstandard compressed data is made of one or more frames.
-// There are two frame formats defined by Zstandard: Zstandard frames and Skippable frames.
-// See https://datatracker.ietf.org/doc/html/rfc8878#section-3 for more details.
-func zstdMatcher() matcher {
- return func(source []byte) bool {
- if bytes.HasPrefix(source, zstdMagic) {
- // Zstandard frame
- return true
- }
- // skippable frame
- if len(source) < 8 {
- return false
- }
- // magic number from 0x184D2A50 to 0x184D2A5F.
- if binary.LittleEndian.Uint32(source[:4])&zstdMagicSkippableMask == zstdMagicSkippableStart {
- return true
- }
- return false
- }
-}
-
// DetectCompression detects the compression algorithm of the source.
-func DetectCompression(source []byte) Compression {
- compressionMap := map[Compression]matcher{
- Bzip2: magicNumberMatcher(bzip2Magic),
- Gzip: magicNumberMatcher(gzipMagic),
- Xz: magicNumberMatcher(xzMagic),
- Zstd: zstdMatcher(),
- }
- for _, compression := range []Compression{Bzip2, Gzip, Xz, Zstd} {
- fn := compressionMap[compression]
- if fn(source) {
- return compression
- }
- }
- return Uncompressed
-}
-
-func xzDecompress(ctx context.Context, archive io.Reader) (io.ReadCloser, error) {
- args := []string{"xz", "-d", "-c", "-q"}
-
- return cmdStream(exec.CommandContext(ctx, args[0], args[1:]...), archive)
-}
-
-func gzDecompress(ctx context.Context, buf io.Reader) (io.ReadCloser, error) {
- if noPigzEnv := os.Getenv("MOBY_DISABLE_PIGZ"); noPigzEnv != "" {
- noPigz, err := strconv.ParseBool(noPigzEnv)
- if err != nil {
- log.G(ctx).WithError(err).Warn("invalid value in MOBY_DISABLE_PIGZ env var")
- }
- if noPigz {
- log.G(ctx).Debugf("Use of pigz is disabled due to MOBY_DISABLE_PIGZ=%s", noPigzEnv)
- return gzip.NewReader(buf)
- }
- }
-
- unpigzPath, err := exec.LookPath("unpigz")
- if err != nil {
- log.G(ctx).Debugf("unpigz binary not found, falling back to go gzip library")
- return gzip.NewReader(buf)
- }
-
- log.G(ctx).Debugf("Using %s to decompress", unpigzPath)
-
- return cmdStream(exec.CommandContext(ctx, unpigzPath, "-d", "-c"), buf)
-}
-
-type readCloserWrapper struct {
- io.Reader
- closer func() error
- closed atomic.Bool
-}
-
-func (r *readCloserWrapper) Close() error {
- if !r.closed.CompareAndSwap(false, true) {
- log.G(context.TODO()).Error("subsequent attempt to close readCloserWrapper")
- if log.GetLevel() >= log.DebugLevel {
- log.G(context.TODO()).Errorf("stack trace: %s", string(debug.Stack()))
- }
-
- return nil
- }
- if r.closer != nil {
- return r.closer()
- }
- return nil
-}
-
-var bufioReader32KPool = &sync.Pool{
- New: func() interface{} { return bufio.NewReaderSize(nil, 32*1024) },
-}
-
-type bufferedReader struct {
- buf *bufio.Reader
-}
-
-func newBufferedReader(r io.Reader) *bufferedReader {
- buf := bufioReader32KPool.Get().(*bufio.Reader)
- buf.Reset(r)
- return &bufferedReader{buf}
-}
-
-func (r *bufferedReader) Read(p []byte) (int, error) {
- if r.buf == nil {
- return 0, io.EOF
- }
- n, err := r.buf.Read(p)
- if err == io.EOF {
- r.buf.Reset(nil)
- bufioReader32KPool.Put(r.buf)
- r.buf = nil
- }
- return n, err
-}
-
-func (r *bufferedReader) Peek(n int) ([]byte, error) {
- if r.buf == nil {
- return nil, io.EOF
- }
- return r.buf.Peek(n)
+//
+// Deprecated: use [compression.Detect].
+func DetectCompression(source []byte) compression.Compression {
+ return compression.Detect(source)
}
// DecompressStream decompresses the archive and returns a ReaderCloser with the decompressed archive.
+//
+// Deprecated: use [compression.DecompressStream].
func DecompressStream(archive io.Reader) (io.ReadCloser, error) {
- buf := newBufferedReader(archive)
- bs, err := buf.Peek(10)
- if err != nil && err != io.EOF {
- // Note: we'll ignore any io.EOF error because there are some odd
- // cases where the layer.tar file will be empty (zero bytes) and
- // that results in an io.EOF from the Peek() call. So, in those
- // cases we'll just treat it as a non-compressed stream and
- // that means just create an empty layer.
- // See Issue 18170
- return nil, err
- }
-
- compression := DetectCompression(bs)
- switch compression {
- case Uncompressed:
- return &readCloserWrapper{
- Reader: buf,
- }, nil
- case Gzip:
- ctx, cancel := context.WithCancel(context.Background())
-
- gzReader, err := gzDecompress(ctx, buf)
- if err != nil {
- cancel()
- return nil, err
- }
- return &readCloserWrapper{
- Reader: gzReader,
- closer: func() error {
- cancel()
- return gzReader.Close()
- },
- }, nil
- case Bzip2:
- bz2Reader := bzip2.NewReader(buf)
- return &readCloserWrapper{
- Reader: bz2Reader,
- }, nil
- case Xz:
- ctx, cancel := context.WithCancel(context.Background())
-
- xzReader, err := xzDecompress(ctx, buf)
- if err != nil {
- cancel()
- return nil, err
- }
-
- return &readCloserWrapper{
- Reader: xzReader,
- closer: func() error {
- cancel()
- return xzReader.Close()
- },
- }, nil
- case Zstd:
- zstdReader, err := zstd.NewReader(buf)
- if err != nil {
- return nil, err
- }
- return &readCloserWrapper{
- Reader: zstdReader,
- closer: func() error {
- zstdReader.Close()
- return nil
- },
- }, nil
- default:
- return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension())
- }
+ return compression.DecompressStream(archive)
}
-type nopWriteCloser struct {
- io.Writer
-}
-
-func (nopWriteCloser) Close() error { return nil }
-
// CompressStream compresses the dest with specified compression algorithm.
-func CompressStream(dest io.Writer, compression Compression) (io.WriteCloser, error) {
- switch compression {
- case Uncompressed:
- return nopWriteCloser{dest}, nil
- case Gzip:
- return gzip.NewWriter(dest), nil
- case Bzip2, Xz:
- // archive/bzip2 does not support writing, and there is no xz support at all
- // However, this is not a problem as docker only currently generates gzipped tars
- return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension())
- default:
- return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension())
- }
+//
+// Deprecated: use [compression.CompressStream].
+func CompressStream(dest io.Writer, comp compression.Compression) (io.WriteCloser, error) {
+ return compression.CompressStream(dest, comp)
}
// TarModifierFunc is a function that can be passed to ReplaceFileTarWrapper to
@@ -411,7 +193,7 @@ func ReplaceFileTarWrapper(inputTarStream io.ReadCloser, mods map[string]TarModi
var originalHeader *tar.Header
for {
originalHeader, err = tarReader.Next()
- if err == io.EOF {
+ if errors.Is(err, io.EOF) {
break
}
if err != nil {
@@ -453,90 +235,11 @@ func ReplaceFileTarWrapper(inputTarStream io.ReadCloser, mods map[string]TarModi
return pipeReader
}
-// Extension returns the extension of a file that uses the specified compression algorithm.
-func (compression *Compression) Extension() string {
- switch *compression {
- case Uncompressed:
- return "tar"
- case Bzip2:
- return "tar.bz2"
- case Gzip:
- return "tar.gz"
- case Xz:
- return "tar.xz"
- case Zstd:
- return "tar.zst"
- }
- return ""
-}
-
-// assert that we implement [tar.FileInfoNames].
-//
-// TODO(thaJeztah): disabled to allow compiling on < go1.23. un-comment once we drop support for older versions of go.
-// var _ tar.FileInfoNames = (*nosysFileInfo)(nil)
-
-// nosysFileInfo hides the system-dependent info of the wrapped FileInfo to
-// prevent tar.FileInfoHeader from introspecting it and potentially calling into
-// glibc.
-//
-// It implements [tar.FileInfoNames] to further prevent [tar.FileInfoHeader]
-// from performing any lookups on go1.23 and up. see https://go.dev/issue/50102
-type nosysFileInfo struct {
- os.FileInfo
-}
-
-// Uname stubs out looking up username. It implements [tar.FileInfoNames]
-// to prevent [tar.FileInfoHeader] from loading libraries to perform
-// username lookups.
-func (fi nosysFileInfo) Uname() (string, error) {
- return "", nil
-}
-
-// Gname stubs out looking up group-name. It implements [tar.FileInfoNames]
-// to prevent [tar.FileInfoHeader] from loading libraries to perform
-// username lookups.
-func (fi nosysFileInfo) Gname() (string, error) {
- return "", nil
-}
-
-func (fi nosysFileInfo) Sys() interface{} {
- // A Sys value of type *tar.Header is safe as it is system-independent.
- // The tar.FileInfoHeader function copies the fields into the returned
- // header without performing any OS lookups.
- if sys, ok := fi.FileInfo.Sys().(*tar.Header); ok {
- return sys
- }
- return nil
-}
-
-// sysStat, if non-nil, populates hdr from system-dependent fields of fi.
-var sysStat func(fi os.FileInfo, hdr *tar.Header) error
-
// FileInfoHeaderNoLookups creates a partially-populated tar.Header from fi.
//
-// Compared to the archive/tar.FileInfoHeader function, this function is safe to
-// call from a chrooted process as it does not populate fields which would
-// require operating system lookups. It behaves identically to
-// tar.FileInfoHeader when fi is a FileInfo value returned from
-// tar.Header.FileInfo().
-//
-// When fi is a FileInfo for a native file, such as returned from os.Stat() and
-// os.Lstat(), the returned Header value differs from one returned from
-// tar.FileInfoHeader in the following ways. The Uname and Gname fields are not
-// set as OS lookups would be required to populate them. The AccessTime and
-// ChangeTime fields are not currently set (not yet implemented) although that
-// is subject to change. Callers which require the AccessTime or ChangeTime
-// fields to be zeroed should explicitly zero them out in the returned Header
-// value to avoid any compatibility issues in the future.
+// Deprecated: use [tarheader.FileInfoHeaderNoLookups].
func FileInfoHeaderNoLookups(fi os.FileInfo, link string) (*tar.Header, error) {
- hdr, err := tar.FileInfoHeader(nosysFileInfo{fi}, link)
- if err != nil {
- return nil, err
- }
- if sysStat != nil {
- return hdr, sysStat(fi, hdr)
- }
- return hdr, nil
+ return tarheader.FileInfoHeaderNoLookups(fi, link)
}
// FileInfoHeader creates a populated Header from fi.
@@ -547,7 +250,7 @@ func FileInfoHeaderNoLookups(fi os.FileInfo, link string) (*tar.Header, error) {
// precision, and the Uname and Gname fields are only set when fi is a FileInfo
// value returned from tar.Header.FileInfo().
func FileInfoHeader(name string, fi os.FileInfo, link string) (*tar.Header, error) {
- hdr, err := FileInfoHeaderNoLookups(fi, link)
+ hdr, err := tarheader.FileInfoHeaderNoLookups(fi, link)
if err != nil {
return nil, err
}
@@ -598,8 +301,8 @@ type tarAppender struct {
// for hardlink mapping
SeenFiles map[uint64]string
- IdentityMapping idtools.IdentityMapping
- ChownOpts *idtools.Identity
+ IdentityMapping user.IdentityMapping
+ ChownOpts *ChownOpts
// For packing and unpacking whiteout files in the
// non standard format. The whiteout files defined
@@ -608,7 +311,7 @@ type tarAppender struct {
WhiteoutConverter tarWhiteoutConverter
}
-func newTarAppender(idMapping idtools.IdentityMapping, writer io.Writer, chownOpts *idtools.Identity) *tarAppender {
+func newTarAppender(idMapping user.IdentityMapping, writer io.Writer, chownOpts *ChownOpts) *tarAppender {
return &tarAppender{
SeenFiles: make(map[uint64]string),
TarWriter: tar.NewWriter(writer),
@@ -679,11 +382,11 @@ func (ta *tarAppender) addTarFile(path, name string) error {
// writing tar headers/files. We skip whiteout files because they were written
// by the kernel and already have proper ownership relative to the host
if !isOverlayWhiteout && !strings.HasPrefix(filepath.Base(hdr.Name), WhiteoutPrefix) && !ta.IdentityMapping.Empty() {
- fileIDPair, err := getFileUIDGID(fi.Sys())
+ uid, gid, err := getFileUIDGID(fi.Sys())
if err != nil {
return err
}
- hdr.Uid, hdr.Gid, err = ta.IdentityMapping.ToContainer(fileIDPair)
+ hdr.Uid, hdr.Gid, err = ta.IdentityMapping.ToContainer(uid, gid)
if err != nil {
return err
}
@@ -743,7 +446,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o
var (
Lchown = true
inUserns, bestEffortXattrs bool
- chownOpts *idtools.Identity
+ chownOpts *ChownOpts
)
// TODO(thaJeztah): make opts a required argument.
@@ -763,7 +466,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o
case tar.TypeDir:
// Create directory unless it exists as a directory already.
// In that case we just want to merge the two
- if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) {
+ if fi, err := os.Lstat(path); err != nil || !fi.IsDir() {
if err := os.Mkdir(path, hdrInfo.Mode()); err != nil {
return err
}
@@ -839,7 +542,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o
// Lchown is not supported on Windows.
if Lchown && runtime.GOOS != "windows" {
if chownOpts == nil {
- chownOpts = &idtools.Identity{UID: hdr.Uid, GID: hdr.Gid}
+ chownOpts = &ChownOpts{UID: hdr.Uid, GID: hdr.Gid}
}
if err := os.Lchown(path, chownOpts.UID, chownOpts.GID); err != nil {
var msg string
@@ -903,8 +606,8 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o
// Tar creates an archive from the directory at `path`, and returns it as a
// stream of bytes.
-func Tar(path string, compression Compression) (io.ReadCloser, error) {
- return TarWithOptions(path, &TarOptions{Compression: compression})
+func Tar(path string, comp compression.Compression) (io.ReadCloser, error) {
+ return TarWithOptions(path, &TarOptions{Compression: comp})
}
// TarWithOptions creates an archive from the directory at `path`, only including files whose relative
@@ -940,7 +643,7 @@ func NewTarballer(srcPath string, options *TarOptions) (*Tarballer, error) {
pipeReader, pipeWriter := io.Pipe()
- compressWriter, err := CompressStream(pipeWriter, options.Compression)
+ compressWriter, err := compression.CompressStream(pipeWriter, options.Compression)
if err != nil {
return nil, err
}
@@ -1026,7 +729,8 @@ func (t *Tarballer) Do() {
)
walkRoot := getWalkRoot(t.srcPath, include)
- filepath.WalkDir(walkRoot, func(filePath string, f os.DirEntry, err error) error {
+ // TODO(thaJeztah): should this error be handled?
+ _ = filepath.WalkDir(walkRoot, func(filePath string, f os.DirEntry, err error) error {
if err != nil {
log.G(context.TODO()).Errorf("Tar: Can't stat file %s to tar: %s", t.srcPath, err)
return nil
@@ -1130,7 +834,7 @@ func (t *Tarballer) Do() {
if err := ta.addTarFile(filePath, relFilePath); err != nil {
log.G(context.TODO()).Errorf("Can't add file %s to tar: %s", filePath, err)
// if pipe is broken, stop writing tar stream to it
- if err == io.ErrClosedPipe {
+ if errors.Is(err, io.ErrClosedPipe) {
return err
}
}
@@ -1150,7 +854,7 @@ func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) err
loop:
for {
hdr, err := tr.Next()
- if err == io.EOF {
+ if errors.Is(err, io.EOF) {
// end of tar archive
break
}
@@ -1212,7 +916,7 @@ loop:
continue
}
- if !(fi.IsDir() && hdr.Typeflag == tar.TypeDir) {
+ if !fi.IsDir() || hdr.Typeflag != tar.TypeDir {
if err := os.RemoveAll(path); err != nil {
return err
}
@@ -1272,9 +976,9 @@ func createImpliedDirectories(dest string, hdr *tar.Header, options *TarOptions)
// RootPair() is confined inside this loop as most cases will not require a call, so we can spend some
// unneeded function calls in the uncommon case to encapsulate logic -- implied directories are a niche
// usage that reduces the portability of an image.
- rootIDs := options.IDMap.RootPair()
+ uid, gid := options.IDMap.RootPair()
- err = idtools.MkdirAllAndChownNew(parentPath, ImpliedDirectoryMode, rootIDs)
+ err = user.MkdirAllAndChown(parentPath, ImpliedDirectoryMode, uid, gid, user.WithOnlyNew)
if err != nil {
return err
}
@@ -1304,7 +1008,7 @@ func UntarUncompressed(tarArchive io.Reader, dest string, options *TarOptions) e
// Handler for teasing out the automatic decompression
func untarHandler(tarArchive io.Reader, dest string, options *TarOptions, decompress bool) error {
if tarArchive == nil {
- return fmt.Errorf("Empty archive")
+ return errors.New("empty archive")
}
dest = filepath.Clean(dest)
if options == nil {
@@ -1316,7 +1020,7 @@ func untarHandler(tarArchive io.Reader, dest string, options *TarOptions, decomp
r := tarArchive
if decompress {
- decompressedArchive, err := DecompressStream(tarArchive)
+ decompressedArchive, err := compression.DecompressStream(tarArchive)
if err != nil {
return err
}
@@ -1330,15 +1034,14 @@ func untarHandler(tarArchive io.Reader, dest string, options *TarOptions, decomp
// TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other.
// If either Tar or Untar fails, TarUntar aborts and returns the error.
func (archiver *Archiver) TarUntar(src, dst string) error {
- archive, err := TarWithOptions(src, &TarOptions{Compression: Uncompressed})
+ archive, err := Tar(src, compression.None)
if err != nil {
return err
}
defer archive.Close()
- options := &TarOptions{
+ return archiver.Untar(archive, dst, &TarOptions{
IDMap: archiver.IDMapping,
- }
- return archiver.Untar(archive, dst, options)
+ })
}
// UntarPath untar a file from path to a destination, src is the source tar file path.
@@ -1348,10 +1051,9 @@ func (archiver *Archiver) UntarPath(src, dst string) error {
return err
}
defer archive.Close()
- options := &TarOptions{
+ return archiver.Untar(archive, dst, &TarOptions{
IDMap: archiver.IDMapping,
- }
- return archiver.Untar(archive, dst, options)
+ })
}
// CopyWithTar creates a tar archive of filesystem path `src`, and
@@ -1370,9 +1072,9 @@ func (archiver *Archiver) CopyWithTar(src, dst string) error {
// if this Archiver is set up with ID mapping we need to create
// the new destination directory with the remapped root UID/GID pair
// as owner
- rootIDs := archiver.IDMapping.RootPair()
+ uid, gid := archiver.IDMapping.RootPair()
// Create dst, copy src's content into it
- if err := idtools.MkdirAllAndChownNew(dst, 0o755, rootIDs); err != nil {
+ if err := user.MkdirAllAndChown(dst, 0o755, uid, gid, user.WithOnlyNew); err != nil {
return err
}
return archiver.TarUntar(src, dst)
@@ -1388,7 +1090,7 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
}
if srcSt.IsDir() {
- return fmt.Errorf("Can't copy a directory")
+ return errors.New("can't copy a directory")
}
// Clean up the trailing slash. This must be done in an operating
@@ -1416,7 +1118,7 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
}
defer srcF.Close()
- hdr, err := FileInfoHeaderNoLookups(srcSt, "")
+ hdr, err := tarheader.FileInfoHeaderNoLookups(srcSt, "")
if err != nil {
return err
}
@@ -1456,52 +1158,12 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
}
// IdentityMapping returns the IdentityMapping of the archiver.
-func (archiver *Archiver) IdentityMapping() idtools.IdentityMapping {
+func (archiver *Archiver) IdentityMapping() user.IdentityMapping {
return archiver.IDMapping
}
-func remapIDs(idMapping idtools.IdentityMapping, hdr *tar.Header) error {
- ids, err := idMapping.ToHost(idtools.Identity{UID: hdr.Uid, GID: hdr.Gid})
- hdr.Uid, hdr.Gid = ids.UID, ids.GID
+func remapIDs(idMapping user.IdentityMapping, hdr *tar.Header) error {
+ uid, gid, err := idMapping.ToHost(hdr.Uid, hdr.Gid)
+ hdr.Uid, hdr.Gid = uid, gid
return err
}
-
-// cmdStream executes a command, and returns its stdout as a stream.
-// If the command fails to run or doesn't complete successfully, an error
-// will be returned, including anything written on stderr.
-func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, error) {
- cmd.Stdin = input
- pipeR, pipeW := io.Pipe()
- cmd.Stdout = pipeW
- var errBuf bytes.Buffer
- cmd.Stderr = &errBuf
-
- // Run the command and return the pipe
- if err := cmd.Start(); err != nil {
- return nil, err
- }
-
- // Ensure the command has exited before we clean anything up
- done := make(chan struct{})
-
- // Copy stdout to the returned pipe
- go func() {
- if err := cmd.Wait(); err != nil {
- pipeW.CloseWithError(fmt.Errorf("%s: %s", err, errBuf.String()))
- } else {
- pipeW.Close()
- }
- close(done)
- }()
-
- return &readCloserWrapper{
- Reader: pipeR,
- closer: func() error {
- // Close pipeR, and then wait for the command to complete before returning. We have to close pipeR first, as
- // cmd.Wait waits for any non-file stdout/stderr/stdin to close.
- err := pipeR.Close()
- <-done
- return err
- },
- }, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_linux.go b/vendor/github.com/moby/go-archive/archive_linux.go
index 7b6c3e0..7b6c3e0 100644
--- a/vendor/github.com/docker/docker/pkg/archive/archive_linux.go
+++ b/vendor/github.com/moby/go-archive/archive_linux.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_other.go b/vendor/github.com/moby/go-archive/archive_other.go
index 6495549..6495549 100644
--- a/vendor/github.com/docker/docker/pkg/archive/archive_other.go
+++ b/vendor/github.com/moby/go-archive/archive_other.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_unix.go b/vendor/github.com/moby/go-archive/archive_unix.go
index bc6b25a..3a9f5b0 100644
--- a/vendor/github.com/docker/docker/pkg/archive/archive_unix.go
+++ b/vendor/github.com/moby/go-archive/archive_unix.go
@@ -7,18 +7,12 @@ import (
"errors"
"os"
"path/filepath"
- "runtime"
"strings"
"syscall"
- "github.com/docker/docker/pkg/idtools"
"golang.org/x/sys/unix"
)
-func init() {
- sysStat = statUnix
-}
-
// addLongPathPrefix adds the Windows long path prefix to the path provided if
// it does not already have it. It is a no-op on platforms other than Windows.
func addLongPathPrefix(srcPath string) string {
@@ -39,40 +33,6 @@ func chmodTarEntry(perm os.FileMode) os.FileMode {
return perm // noop for unix as golang APIs provide perm bits correctly
}
-// statUnix populates hdr from system-dependent fields of fi without performing
-// any OS lookups.
-func statUnix(fi os.FileInfo, hdr *tar.Header) error {
- // Devmajor and Devminor are only needed for special devices.
-
- // In FreeBSD, RDev for regular files is -1 (unless overridden by FS):
- // https://cgit.freebsd.org/src/tree/sys/kern/vfs_default.c?h=stable/13#n1531
- // (NODEV is -1: https://cgit.freebsd.org/src/tree/sys/sys/param.h?h=stable/13#n241).
-
- // ZFS in particular does not override the default:
- // https://cgit.freebsd.org/src/tree/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c?h=stable/13#n2027
-
- // Since `Stat_t.Rdev` is uint64, the cast turns -1 into (2^64 - 1).
- // Such large values cannot be encoded in a tar header.
- if runtime.GOOS == "freebsd" && hdr.Typeflag != tar.TypeBlock && hdr.Typeflag != tar.TypeChar {
- return nil
- }
- s, ok := fi.Sys().(*syscall.Stat_t)
- if !ok {
- return nil
- }
-
- hdr.Uid = int(s.Uid)
- hdr.Gid = int(s.Gid)
-
- if s.Mode&unix.S_IFBLK != 0 ||
- s.Mode&unix.S_IFCHR != 0 {
- hdr.Devmajor = int64(unix.Major(uint64(s.Rdev))) //nolint: unconvert
- hdr.Devminor = int64(unix.Minor(uint64(s.Rdev))) //nolint: unconvert
- }
-
- return nil
-}
-
func getInodeFromStat(stat interface{}) (uint64, error) {
s, ok := stat.(*syscall.Stat_t)
if !ok {
@@ -82,13 +42,13 @@ func getInodeFromStat(stat interface{}) (uint64, error) {
return s.Ino, nil
}
-func getFileUIDGID(stat interface{}) (idtools.Identity, error) {
+func getFileUIDGID(stat interface{}) (int, int, error) {
s, ok := stat.(*syscall.Stat_t)
if !ok {
- return idtools.Identity{}, errors.New("cannot convert stat value to syscall.Stat_t")
+ return 0, 0, errors.New("cannot convert stat value to syscall.Stat_t")
}
- return idtools.Identity{UID: int(s.Uid), GID: int(s.Gid)}, nil
+ return int(s.Uid), int(s.Gid), nil
}
// handleTarTypeBlockCharFifo is an OS-specific helper function used by
diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_windows.go b/vendor/github.com/moby/go-archive/archive_windows.go
index fd2546e..0e3e316 100644
--- a/vendor/github.com/docker/docker/pkg/archive/archive_windows.go
+++ b/vendor/github.com/moby/go-archive/archive_windows.go
@@ -5,8 +5,6 @@ import (
"os"
"path/filepath"
"strings"
-
- "github.com/docker/docker/pkg/idtools"
)
// longPathPrefix is the longpath prefix for Windows file paths.
@@ -43,11 +41,6 @@ func chmodTarEntry(perm os.FileMode) os.FileMode {
return perm | 0o111
}
-func setHeaderForSpecialDevice(hdr *tar.Header, name string, stat interface{}) (err error) {
- // do nothing. no notion of Rdev, Nlink in stat on Windows
- return
-}
-
func getInodeFromStat(stat interface{}) (uint64, error) {
// do nothing. no notion of Inode in stat on Windows
return 0, nil
@@ -63,7 +56,7 @@ func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error {
return nil
}
-func getFileUIDGID(stat interface{}) (idtools.Identity, error) {
+func getFileUIDGID(stat interface{}) (int, int, error) {
// no notion of file ownership mapping yet on Windows
- return idtools.Identity{UID: 0, GID: 0}, nil
+ return 0, 0, nil
}
diff --git a/vendor/github.com/docker/docker/pkg/archive/changes.go b/vendor/github.com/moby/go-archive/changes.go
index 1c0509d..02a0372 100644
--- a/vendor/github.com/docker/docker/pkg/archive/changes.go
+++ b/vendor/github.com/moby/go-archive/changes.go
@@ -14,7 +14,7 @@ import (
"time"
"github.com/containerd/log"
- "github.com/docker/docker/pkg/idtools"
+ "github.com/moby/sys/user"
)
// ChangeType represents the change type.
@@ -75,7 +75,7 @@ func sameFsTime(a, b time.Time) bool {
// Changes walks the path rw and determines changes for the files in the path,
// with respect to the parent layers
func Changes(layers []string, rw string) ([]Change, error) {
- return changes(layers, rw, aufsDeletedFile, aufsMetadataSkip)
+ return collectChanges(layers, rw, aufsDeletedFile, aufsMetadataSkip)
}
func aufsMetadataSkip(path string) (skip bool, err error) {
@@ -103,7 +103,7 @@ type (
deleteChange func(string, string, os.FileInfo) (string, error)
)
-func changes(layers []string, rw string, dc deleteChange, sc skipChange) ([]Change, error) {
+func collectChanges(layers []string, rw string, dc deleteChange, sc skipChange) ([]Change, error) {
var (
changes []Change
changedDirs = make(map[string]struct{})
@@ -383,7 +383,7 @@ func ChangesSize(newDir string, changes []Change) int64 {
}
// ExportChanges produces an Archive from the provided changes, relative to dir.
-func ExportChanges(dir string, changes []Change, idMap idtools.IdentityMapping) (io.ReadCloser, error) {
+func ExportChanges(dir string, changes []Change, idMap user.IdentityMapping) (io.ReadCloser, error) {
reader, writer := io.Pipe()
go func() {
ta := newTarAppender(idMap, writer, nil)
diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_linux.go b/vendor/github.com/moby/go-archive/changes_linux.go
index 9a041b0..8289fe1 100644
--- a/vendor/github.com/docker/docker/pkg/archive/changes_linux.go
+++ b/vendor/github.com/moby/go-archive/changes_linux.go
@@ -132,14 +132,7 @@ func (w *walker) walk(path string, i1, i2 os.FileInfo) (err error) {
ix1 := 0
ix2 := 0
- for {
- if ix1 >= len(names1) {
- break
- }
- if ix2 >= len(names2) {
- break
- }
-
+ for ix1 < len(names1) && ix2 < len(names2) {
ni1 := names1[ix1]
ni2 := names2[ix2]
diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_other.go b/vendor/github.com/moby/go-archive/changes_other.go
index a8a3a5a..a8a3a5a 100644
--- a/vendor/github.com/docker/docker/pkg/archive/changes_other.go
+++ b/vendor/github.com/moby/go-archive/changes_other.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_unix.go b/vendor/github.com/moby/go-archive/changes_unix.go
index 4dd98bd..4dd98bd 100644
--- a/vendor/github.com/docker/docker/pkg/archive/changes_unix.go
+++ b/vendor/github.com/moby/go-archive/changes_unix.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_windows.go b/vendor/github.com/moby/go-archive/changes_windows.go
index c89605c..c89605c 100644
--- a/vendor/github.com/docker/docker/pkg/archive/changes_windows.go
+++ b/vendor/github.com/moby/go-archive/changes_windows.go
diff --git a/vendor/github.com/moby/go-archive/compression/compression.go b/vendor/github.com/moby/go-archive/compression/compression.go
new file mode 100644
index 0000000..e298cef
--- /dev/null
+++ b/vendor/github.com/moby/go-archive/compression/compression.go
@@ -0,0 +1,263 @@
+package compression
+
+import (
+ "bufio"
+ "bytes"
+ "compress/bzip2"
+ "compress/gzip"
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "os/exec"
+ "strconv"
+ "sync"
+
+ "github.com/containerd/log"
+ "github.com/klauspost/compress/zstd"
+)
+
+// Compression is the state represents if compressed or not.
+type Compression int
+
+const (
+ None Compression = 0 // None represents the uncompressed.
+ Bzip2 Compression = 1 // Bzip2 is bzip2 compression algorithm.
+ Gzip Compression = 2 // Gzip is gzip compression algorithm.
+ Xz Compression = 3 // Xz is xz compression algorithm.
+ Zstd Compression = 4 // Zstd is zstd compression algorithm.
+)
+
+// Extension returns the extension of a file that uses the specified compression algorithm.
+func (c *Compression) Extension() string {
+ switch *c {
+ case None:
+ return "tar"
+ case Bzip2:
+ return "tar.bz2"
+ case Gzip:
+ return "tar.gz"
+ case Xz:
+ return "tar.xz"
+ case Zstd:
+ return "tar.zst"
+ default:
+ return ""
+ }
+}
+
+type readCloserWrapper struct {
+ io.Reader
+ closer func() error
+}
+
+func (r *readCloserWrapper) Close() error {
+ if r.closer != nil {
+ return r.closer()
+ }
+ return nil
+}
+
+type nopWriteCloser struct {
+ io.Writer
+}
+
+func (nopWriteCloser) Close() error { return nil }
+
+var bufioReader32KPool = &sync.Pool{
+ New: func() interface{} { return bufio.NewReaderSize(nil, 32*1024) },
+}
+
+type bufferedReader struct {
+ buf *bufio.Reader
+}
+
+func newBufferedReader(r io.Reader) *bufferedReader {
+ buf := bufioReader32KPool.Get().(*bufio.Reader)
+ buf.Reset(r)
+ return &bufferedReader{buf}
+}
+
+func (r *bufferedReader) Read(p []byte) (int, error) {
+ if r.buf == nil {
+ return 0, io.EOF
+ }
+ n, err := r.buf.Read(p)
+ if errors.Is(err, io.EOF) {
+ r.buf.Reset(nil)
+ bufioReader32KPool.Put(r.buf)
+ r.buf = nil
+ }
+ return n, err
+}
+
+func (r *bufferedReader) Peek(n int) ([]byte, error) {
+ if r.buf == nil {
+ return nil, io.EOF
+ }
+ return r.buf.Peek(n)
+}
+
+// DecompressStream decompresses the archive and returns a ReaderCloser with the decompressed archive.
+func DecompressStream(archive io.Reader) (io.ReadCloser, error) {
+ buf := newBufferedReader(archive)
+ bs, err := buf.Peek(10)
+ if err != nil && !errors.Is(err, io.EOF) {
+ // Note: we'll ignore any io.EOF error because there are some odd
+ // cases where the layer.tar file will be empty (zero bytes) and
+ // that results in an io.EOF from the Peek() call. So, in those
+ // cases we'll just treat it as a non-compressed stream and
+ // that means just create an empty layer.
+ // See Issue 18170
+ return nil, err
+ }
+
+ switch compression := Detect(bs); compression {
+ case None:
+ return &readCloserWrapper{
+ Reader: buf,
+ }, nil
+ case Gzip:
+ ctx, cancel := context.WithCancel(context.Background())
+ gzReader, err := gzipDecompress(ctx, buf)
+ if err != nil {
+ cancel()
+ return nil, err
+ }
+
+ return &readCloserWrapper{
+ Reader: gzReader,
+ closer: func() error {
+ cancel()
+ return gzReader.Close()
+ },
+ }, nil
+ case Bzip2:
+ bz2Reader := bzip2.NewReader(buf)
+ return &readCloserWrapper{
+ Reader: bz2Reader,
+ }, nil
+ case Xz:
+ ctx, cancel := context.WithCancel(context.Background())
+
+ xzReader, err := xzDecompress(ctx, buf)
+ if err != nil {
+ cancel()
+ return nil, err
+ }
+
+ return &readCloserWrapper{
+ Reader: xzReader,
+ closer: func() error {
+ cancel()
+ return xzReader.Close()
+ },
+ }, nil
+ case Zstd:
+ zstdReader, err := zstd.NewReader(buf)
+ if err != nil {
+ return nil, err
+ }
+ return &readCloserWrapper{
+ Reader: zstdReader,
+ closer: func() error {
+ zstdReader.Close()
+ return nil
+ },
+ }, nil
+
+ default:
+ return nil, fmt.Errorf("unsupported compression format (%d)", compression)
+ }
+}
+
+// CompressStream compresses the dest with specified compression algorithm.
+func CompressStream(dest io.Writer, compression Compression) (io.WriteCloser, error) {
+ switch compression {
+ case None:
+ return nopWriteCloser{dest}, nil
+ case Gzip:
+ return gzip.NewWriter(dest), nil
+ case Bzip2:
+ // archive/bzip2 does not support writing.
+ return nil, errors.New("unsupported compression format: tar.bz2")
+ case Xz:
+ // there is no xz support at all
+ // However, this is not a problem as docker only currently generates gzipped tars
+ return nil, errors.New("unsupported compression format: tar.xz")
+ default:
+ return nil, fmt.Errorf("unsupported compression format (%d)", compression)
+ }
+}
+
+func xzDecompress(ctx context.Context, archive io.Reader) (io.ReadCloser, error) {
+ args := []string{"xz", "-d", "-c", "-q"}
+
+ return cmdStream(exec.CommandContext(ctx, args[0], args[1:]...), archive)
+}
+
+func gzipDecompress(ctx context.Context, buf io.Reader) (io.ReadCloser, error) {
+ if noPigzEnv := os.Getenv("MOBY_DISABLE_PIGZ"); noPigzEnv != "" {
+ noPigz, err := strconv.ParseBool(noPigzEnv)
+ if err != nil {
+ log.G(ctx).WithError(err).Warn("invalid value in MOBY_DISABLE_PIGZ env var")
+ }
+ if noPigz {
+ log.G(ctx).Debugf("Use of pigz is disabled due to MOBY_DISABLE_PIGZ=%s", noPigzEnv)
+ return gzip.NewReader(buf)
+ }
+ }
+
+ unpigzPath, err := exec.LookPath("unpigz")
+ if err != nil {
+ log.G(ctx).Debugf("unpigz binary not found, falling back to go gzip library")
+ return gzip.NewReader(buf)
+ }
+
+ log.G(ctx).Debugf("Using %s to decompress", unpigzPath)
+
+ return cmdStream(exec.CommandContext(ctx, unpigzPath, "-d", "-c"), buf)
+}
+
+// cmdStream executes a command, and returns its stdout as a stream.
+// If the command fails to run or doesn't complete successfully, an error
+// will be returned, including anything written on stderr.
+func cmdStream(cmd *exec.Cmd, in io.Reader) (io.ReadCloser, error) {
+ reader, writer := io.Pipe()
+
+ cmd.Stdin = in
+ cmd.Stdout = writer
+
+ var errBuf bytes.Buffer
+ cmd.Stderr = &errBuf
+
+ // Run the command and return the pipe
+ if err := cmd.Start(); err != nil {
+ return nil, err
+ }
+
+ // Ensure the command has exited before we clean anything up
+ done := make(chan struct{})
+
+ // Copy stdout to the returned pipe
+ go func() {
+ if err := cmd.Wait(); err != nil {
+ _ = writer.CloseWithError(fmt.Errorf("%w: %s", err, errBuf.String()))
+ } else {
+ _ = writer.Close()
+ }
+ close(done)
+ }()
+
+ return &readCloserWrapper{
+ Reader: reader,
+ closer: func() error {
+ // Close pipeR, and then wait for the command to complete before returning. We have to close pipeR first, as
+ // cmd.Wait waits for any non-file stdout/stderr/stdin to close.
+ err := reader.Close()
+ <-done
+ return err
+ },
+ }, nil
+}
diff --git a/vendor/github.com/moby/go-archive/compression/compression_detect.go b/vendor/github.com/moby/go-archive/compression/compression_detect.go
new file mode 100644
index 0000000..85eda92
--- /dev/null
+++ b/vendor/github.com/moby/go-archive/compression/compression_detect.go
@@ -0,0 +1,65 @@
+package compression
+
+import (
+ "bytes"
+ "encoding/binary"
+)
+
+const (
+ zstdMagicSkippableStart = 0x184D2A50
+ zstdMagicSkippableMask = 0xFFFFFFF0
+)
+
+var (
+ bzip2Magic = []byte{0x42, 0x5A, 0x68}
+ gzipMagic = []byte{0x1F, 0x8B, 0x08}
+ xzMagic = []byte{0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}
+ zstdMagic = []byte{0x28, 0xb5, 0x2f, 0xfd}
+)
+
+type matcher = func([]byte) bool
+
+// Detect detects the compression algorithm of the source.
+func Detect(source []byte) Compression {
+ compressionMap := map[Compression]matcher{
+ Bzip2: magicNumberMatcher(bzip2Magic),
+ Gzip: magicNumberMatcher(gzipMagic),
+ Xz: magicNumberMatcher(xzMagic),
+ Zstd: zstdMatcher(),
+ }
+ for _, compression := range []Compression{Bzip2, Gzip, Xz, Zstd} {
+ fn := compressionMap[compression]
+ if fn(source) {
+ return compression
+ }
+ }
+ return None
+}
+
+func magicNumberMatcher(m []byte) matcher {
+ return func(source []byte) bool {
+ return bytes.HasPrefix(source, m)
+ }
+}
+
+// zstdMatcher detects zstd compression algorithm.
+// Zstandard compressed data is made of one or more frames.
+// There are two frame formats defined by Zstandard: Zstandard frames and Skippable frames.
+// See https://datatracker.ietf.org/doc/html/rfc8878#section-3 for more details.
+func zstdMatcher() matcher {
+ return func(source []byte) bool {
+ if bytes.HasPrefix(source, zstdMagic) {
+ // Zstandard frame
+ return true
+ }
+ // skippable frame
+ if len(source) < 8 {
+ return false
+ }
+ // magic number from 0x184D2A50 to 0x184D2A5F.
+ if binary.LittleEndian.Uint32(source[:4])&zstdMagicSkippableMask == zstdMagicSkippableStart {
+ return true
+ }
+ return false
+ }
+}
diff --git a/vendor/github.com/docker/docker/pkg/archive/copy.go b/vendor/github.com/moby/go-archive/copy.go
index cae0173..77d038c 100644
--- a/vendor/github.com/docker/docker/pkg/archive/copy.go
+++ b/vendor/github.com/moby/go-archive/copy.go
@@ -128,7 +128,6 @@ func TarResourceRebase(sourcePath, rebaseName string) (content io.ReadCloser, _
func TarResourceRebaseOpts(sourceBase string, rebaseName string) *TarOptions {
filter := []string{sourceBase}
return &TarOptions{
- Compression: Uncompressed,
IncludeFiles: filter,
IncludeSourceDir: true,
RebaseNames: map[string]string{
@@ -335,7 +334,7 @@ func RebaseArchiveEntries(srcContent io.Reader, oldBase, newBase string) io.Read
for {
hdr, err := srcTar.Next()
- if err == io.EOF {
+ if errors.Is(err, io.EOF) {
// Signals end of archive.
rebasedTar.Close()
w.Close()
diff --git a/vendor/github.com/docker/docker/pkg/archive/copy_unix.go b/vendor/github.com/moby/go-archive/copy_unix.go
index f579282..f579282 100644
--- a/vendor/github.com/docker/docker/pkg/archive/copy_unix.go
+++ b/vendor/github.com/moby/go-archive/copy_unix.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/copy_windows.go b/vendor/github.com/moby/go-archive/copy_windows.go
index 2b775b4..2b775b4 100644
--- a/vendor/github.com/docker/docker/pkg/archive/copy_windows.go
+++ b/vendor/github.com/moby/go-archive/copy_windows.go
diff --git a/vendor/github.com/moby/go-archive/dev_freebsd.go b/vendor/github.com/moby/go-archive/dev_freebsd.go
new file mode 100644
index 0000000..b3068fc
--- /dev/null
+++ b/vendor/github.com/moby/go-archive/dev_freebsd.go
@@ -0,0 +1,9 @@
+//go:build freebsd
+
+package archive
+
+import "golang.org/x/sys/unix"
+
+func mknod(path string, mode uint32, dev uint64) error {
+ return unix.Mknod(path, mode, dev)
+}
diff --git a/vendor/github.com/docker/docker/pkg/archive/dev_unix.go b/vendor/github.com/moby/go-archive/dev_unix.go
index dffc596..dffc596 100644
--- a/vendor/github.com/docker/docker/pkg/archive/dev_unix.go
+++ b/vendor/github.com/moby/go-archive/dev_unix.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/diff.go b/vendor/github.com/moby/go-archive/diff.go
index d5a394c..96db972 100644
--- a/vendor/github.com/docker/docker/pkg/archive/diff.go
+++ b/vendor/github.com/moby/go-archive/diff.go
@@ -3,6 +3,7 @@ package archive
import (
"archive/tar"
"context"
+ "errors"
"fmt"
"io"
"os"
@@ -11,6 +12,8 @@ import (
"strings"
"github.com/containerd/log"
+
+ "github.com/moby/go-archive/compression"
)
// UnpackLayer unpack `layer` to a `dest`. The stream `layer` can be
@@ -35,7 +38,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
// Iterate through the files in the archive.
for {
hdr, err := tr.Next()
- if err == io.EOF {
+ if errors.Is(err, io.EOF) {
// end of tar archive
break
}
@@ -149,7 +152,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
// the layer is also a directory. Then we want to merge them (i.e.
// just apply the metadata from the layer).
if fi, err := os.Lstat(path); err == nil {
- if !(fi.IsDir() && hdr.Typeflag == tar.TypeDir) {
+ if !fi.IsDir() || hdr.Typeflag != tar.TypeDir {
if err := os.RemoveAll(path); err != nil {
return 0, err
}
@@ -165,7 +168,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
linkBasename := filepath.Base(hdr.Linkname)
srcHdr = aufsHardlinks[linkBasename]
if srcHdr == nil {
- return 0, fmt.Errorf("Invalid aufs hardlink")
+ return 0, errors.New("invalid aufs hardlink")
}
tmpFile, err := os.Open(filepath.Join(aufsTempdir, linkBasename))
if err != nil {
@@ -221,18 +224,18 @@ func ApplyUncompressedLayer(dest string, layer io.Reader, options *TarOptions) (
// IsEmpty checks if the tar archive is empty (doesn't contain any entries).
func IsEmpty(rd io.Reader) (bool, error) {
- decompRd, err := DecompressStream(rd)
+ decompRd, err := compression.DecompressStream(rd)
if err != nil {
- return true, fmt.Errorf("failed to decompress archive: %v", err)
+ return true, fmt.Errorf("failed to decompress archive: %w", err)
}
defer decompRd.Close()
tarReader := tar.NewReader(decompRd)
if _, err := tarReader.Next(); err != nil {
- if err == io.EOF {
+ if errors.Is(err, io.EOF) {
return true, nil
}
- return false, fmt.Errorf("failed to read next archive header: %v", err)
+ return false, fmt.Errorf("failed to read next archive header: %w", err)
}
return false, nil
@@ -247,7 +250,7 @@ func applyLayerHandler(dest string, layer io.Reader, options *TarOptions, decomp
defer restore()
if decompress {
- decompLayer, err := DecompressStream(layer)
+ decompLayer, err := compression.DecompressStream(layer)
if err != nil {
return 0, err
}
diff --git a/vendor/github.com/docker/docker/pkg/archive/diff_unix.go b/vendor/github.com/moby/go-archive/diff_unix.go
index 7216f2f..7216f2f 100644
--- a/vendor/github.com/docker/docker/pkg/archive/diff_unix.go
+++ b/vendor/github.com/moby/go-archive/diff_unix.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/diff_windows.go b/vendor/github.com/moby/go-archive/diff_windows.go
index d28f5b2..d28f5b2 100644
--- a/vendor/github.com/docker/docker/pkg/archive/diff_windows.go
+++ b/vendor/github.com/moby/go-archive/diff_windows.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/path.go b/vendor/github.com/moby/go-archive/path.go
index 888a697..888a697 100644
--- a/vendor/github.com/docker/docker/pkg/archive/path.go
+++ b/vendor/github.com/moby/go-archive/path.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/path_unix.go b/vendor/github.com/moby/go-archive/path_unix.go
index 390264b..390264b 100644
--- a/vendor/github.com/docker/docker/pkg/archive/path_unix.go
+++ b/vendor/github.com/moby/go-archive/path_unix.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/path_windows.go b/vendor/github.com/moby/go-archive/path_windows.go
index 7e18c8e..7e18c8e 100644
--- a/vendor/github.com/docker/docker/pkg/archive/path_windows.go
+++ b/vendor/github.com/moby/go-archive/path_windows.go
diff --git a/vendor/github.com/moby/go-archive/tarheader/tarheader.go b/vendor/github.com/moby/go-archive/tarheader/tarheader.go
new file mode 100644
index 0000000..03732a4
--- /dev/null
+++ b/vendor/github.com/moby/go-archive/tarheader/tarheader.go
@@ -0,0 +1,67 @@
+package tarheader
+
+import (
+ "archive/tar"
+ "os"
+)
+
+// assert that we implement [tar.FileInfoNames].
+var _ tar.FileInfoNames = (*nosysFileInfo)(nil)
+
+// nosysFileInfo hides the system-dependent info of the wrapped FileInfo to
+// prevent tar.FileInfoHeader from introspecting it and potentially calling into
+// glibc.
+//
+// It implements [tar.FileInfoNames] to further prevent [tar.FileInfoHeader]
+// from performing any lookups on go1.23 and up. see https://go.dev/issue/50102
+type nosysFileInfo struct {
+ os.FileInfo
+}
+
+// Uname stubs out looking up username. It implements [tar.FileInfoNames]
+// to prevent [tar.FileInfoHeader] from loading libraries to perform
+// username lookups.
+func (fi nosysFileInfo) Uname() (string, error) {
+ return "", nil
+}
+
+// Gname stubs out looking up group-name. It implements [tar.FileInfoNames]
+// to prevent [tar.FileInfoHeader] from loading libraries to perform
+// username lookups.
+func (fi nosysFileInfo) Gname() (string, error) {
+ return "", nil
+}
+
+func (fi nosysFileInfo) Sys() interface{} {
+ // A Sys value of type *tar.Header is safe as it is system-independent.
+ // The tar.FileInfoHeader function copies the fields into the returned
+ // header without performing any OS lookups.
+ if sys, ok := fi.FileInfo.Sys().(*tar.Header); ok {
+ return sys
+ }
+ return nil
+}
+
+// FileInfoHeaderNoLookups creates a partially-populated tar.Header from fi.
+//
+// Compared to the archive/tar.FileInfoHeader function, this function is safe to
+// call from a chrooted process as it does not populate fields which would
+// require operating system lookups. It behaves identically to
+// tar.FileInfoHeader when fi is a FileInfo value returned from
+// tar.Header.FileInfo().
+//
+// When fi is a FileInfo for a native file, such as returned from os.Stat() and
+// os.Lstat(), the returned Header value differs from one returned from
+// tar.FileInfoHeader in the following ways. The Uname and Gname fields are not
+// set as OS lookups would be required to populate them. The AccessTime and
+// ChangeTime fields are not currently set (not yet implemented) although that
+// is subject to change. Callers which require the AccessTime or ChangeTime
+// fields to be zeroed should explicitly zero them out in the returned Header
+// value to avoid any compatibility issues in the future.
+func FileInfoHeaderNoLookups(fi os.FileInfo, link string) (*tar.Header, error) {
+ hdr, err := tar.FileInfoHeader(nosysFileInfo{fi}, link)
+ if err != nil {
+ return nil, err
+ }
+ return hdr, sysStat(fi, hdr)
+}
diff --git a/vendor/github.com/moby/go-archive/tarheader/tarheader_unix.go b/vendor/github.com/moby/go-archive/tarheader/tarheader_unix.go
new file mode 100644
index 0000000..9c3311c
--- /dev/null
+++ b/vendor/github.com/moby/go-archive/tarheader/tarheader_unix.go
@@ -0,0 +1,46 @@
+//go:build !windows
+
+package tarheader
+
+import (
+ "archive/tar"
+ "os"
+ "runtime"
+ "syscall"
+
+ "golang.org/x/sys/unix"
+)
+
+// sysStat populates hdr from system-dependent fields of fi without performing
+// any OS lookups.
+func sysStat(fi os.FileInfo, hdr *tar.Header) error {
+ // Devmajor and Devminor are only needed for special devices.
+
+ // In FreeBSD, RDev for regular files is -1 (unless overridden by FS):
+ // https://cgit.freebsd.org/src/tree/sys/kern/vfs_default.c?h=stable/13#n1531
+ // (NODEV is -1: https://cgit.freebsd.org/src/tree/sys/sys/param.h?h=stable/13#n241).
+
+ // ZFS in particular does not override the default:
+ // https://cgit.freebsd.org/src/tree/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c?h=stable/13#n2027
+
+ // Since `Stat_t.Rdev` is uint64, the cast turns -1 into (2^64 - 1).
+ // Such large values cannot be encoded in a tar header.
+ if runtime.GOOS == "freebsd" && hdr.Typeflag != tar.TypeBlock && hdr.Typeflag != tar.TypeChar {
+ return nil
+ }
+ s, ok := fi.Sys().(*syscall.Stat_t)
+ if !ok {
+ return nil
+ }
+
+ hdr.Uid = int(s.Uid)
+ hdr.Gid = int(s.Gid)
+
+ if s.Mode&unix.S_IFBLK != 0 ||
+ s.Mode&unix.S_IFCHR != 0 {
+ hdr.Devmajor = int64(unix.Major(uint64(s.Rdev))) //nolint: unconvert
+ hdr.Devminor = int64(unix.Minor(uint64(s.Rdev))) //nolint: unconvert
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/moby/go-archive/tarheader/tarheader_windows.go b/vendor/github.com/moby/go-archive/tarheader/tarheader_windows.go
new file mode 100644
index 0000000..5d4483c
--- /dev/null
+++ b/vendor/github.com/moby/go-archive/tarheader/tarheader_windows.go
@@ -0,0 +1,12 @@
+package tarheader
+
+import (
+ "archive/tar"
+ "os"
+)
+
+// sysStat populates hdr from system-dependent fields of fi without performing
+// any OS lookups. It is a no-op on Windows.
+func sysStat(os.FileInfo, *tar.Header) error {
+ return nil
+}
diff --git a/vendor/github.com/docker/docker/pkg/archive/time.go b/vendor/github.com/moby/go-archive/time.go
index 4e9ae95..4e9ae95 100644
--- a/vendor/github.com/docker/docker/pkg/archive/time.go
+++ b/vendor/github.com/moby/go-archive/time.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/time_nonwindows.go b/vendor/github.com/moby/go-archive/time_nonwindows.go
index 5bfdfa2..5bfdfa2 100644
--- a/vendor/github.com/docker/docker/pkg/archive/time_nonwindows.go
+++ b/vendor/github.com/moby/go-archive/time_nonwindows.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/time_windows.go b/vendor/github.com/moby/go-archive/time_windows.go
index af1f7c8..af1f7c8 100644
--- a/vendor/github.com/docker/docker/pkg/archive/time_windows.go
+++ b/vendor/github.com/moby/go-archive/time_windows.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/whiteouts.go b/vendor/github.com/moby/go-archive/whiteouts.go
index d20478a..d20478a 100644
--- a/vendor/github.com/docker/docker/pkg/archive/whiteouts.go
+++ b/vendor/github.com/moby/go-archive/whiteouts.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/wrap.go b/vendor/github.com/moby/go-archive/wrap.go
index f8a9725..f8a9725 100644
--- a/vendor/github.com/docker/docker/pkg/archive/wrap.go
+++ b/vendor/github.com/moby/go-archive/wrap.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/xattr_supported.go b/vendor/github.com/moby/go-archive/xattr_supported.go
index 652a1f0..652a1f0 100644
--- a/vendor/github.com/docker/docker/pkg/archive/xattr_supported.go
+++ b/vendor/github.com/moby/go-archive/xattr_supported.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/xattr_supported_linux.go b/vendor/github.com/moby/go-archive/xattr_supported_linux.go
index f2e7646..f2e7646 100644
--- a/vendor/github.com/docker/docker/pkg/archive/xattr_supported_linux.go
+++ b/vendor/github.com/moby/go-archive/xattr_supported_linux.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/xattr_supported_unix.go b/vendor/github.com/moby/go-archive/xattr_supported_unix.go
index 4d88241..4d88241 100644
--- a/vendor/github.com/docker/docker/pkg/archive/xattr_supported_unix.go
+++ b/vendor/github.com/moby/go-archive/xattr_supported_unix.go
diff --git a/vendor/github.com/docker/docker/pkg/archive/xattr_unsupported.go b/vendor/github.com/moby/go-archive/xattr_unsupported.go
index b0d9165..b0d9165 100644
--- a/vendor/github.com/docker/docker/pkg/archive/xattr_unsupported.go
+++ b/vendor/github.com/moby/go-archive/xattr_unsupported.go
diff --git a/vendor/github.com/moby/sys/sequential/sequential_unix.go b/vendor/github.com/moby/sys/sequential/sequential_unix.go
index a3c7340..278cdfb 100644
--- a/vendor/github.com/moby/sys/sequential/sequential_unix.go
+++ b/vendor/github.com/moby/sys/sequential/sequential_unix.go
@@ -5,41 +5,22 @@ package sequential
import "os"
-// Create creates the named file with mode 0666 (before umask), truncating
-// it if it already exists. If successful, methods on the returned
-// File can be used for I/O; the associated file descriptor has mode
-// O_RDWR.
-// If there is an error, it will be of type *PathError.
+// Create is an alias for [os.Create] on non-Windows platforms.
func Create(name string) (*os.File, error) {
return os.Create(name)
}
-// Open opens the named file for reading. If successful, methods on
-// the returned file can be used for reading; the associated file
-// descriptor has mode O_RDONLY.
-// If there is an error, it will be of type *PathError.
+// Open is an alias for [os.Open] on non-Windows platforms.
func Open(name string) (*os.File, error) {
return os.Open(name)
}
-// OpenFile is the generalized open call; most users will use Open
-// or Create instead. It opens the named file with specified flag
-// (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful,
-// methods on the returned File can be used for I/O.
-// If there is an error, it will be of type *PathError.
+// OpenFile is an alias for [os.OpenFile] on non-Windows platforms.
func OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) {
return os.OpenFile(name, flag, perm)
}
-// CreateTemp creates a new temporary file in the directory dir
-// with a name beginning with prefix, opens the file for reading
-// and writing, and returns the resulting *os.File.
-// If dir is the empty string, TempFile uses the default directory
-// for temporary files (see os.TempDir).
-// Multiple programs calling TempFile simultaneously
-// will not choose the same file. The caller can use f.Name()
-// to find the pathname of the file. It is the caller's responsibility
-// to remove the file when no longer needed.
+// CreateTemp is an alias for [os.CreateTemp] on non-Windows platforms.
func CreateTemp(dir, prefix string) (f *os.File, err error) {
return os.CreateTemp(dir, prefix)
}
diff --git a/vendor/github.com/moby/sys/sequential/sequential_windows.go b/vendor/github.com/moby/sys/sequential/sequential_windows.go
index 3f7f0d8..3500ecc 100644
--- a/vendor/github.com/moby/sys/sequential/sequential_windows.go
+++ b/vendor/github.com/moby/sys/sequential/sequential_windows.go
@@ -5,48 +5,52 @@ import (
"path/filepath"
"strconv"
"sync"
- "syscall"
"time"
"unsafe"
"golang.org/x/sys/windows"
)
-// Create creates the named file with mode 0666 (before umask), truncating
-// it if it already exists. If successful, methods on the returned
-// File can be used for I/O; the associated file descriptor has mode
-// O_RDWR.
-// If there is an error, it will be of type *PathError.
+// Create is a copy of [os.Create], modified to use sequential file access.
+//
+// It uses [windows.FILE_FLAG_SEQUENTIAL_SCAN] rather than [windows.FILE_ATTRIBUTE_NORMAL]
+// as implemented in golang. Refer to the [Win32 API documentation] for details
+// on sequential file access.
+//
+// [Win32 API documentation]: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#FILE_FLAG_SEQUENTIAL_SCAN
func Create(name string) (*os.File, error) {
- return OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0)
+ return openFileSequential(name, windows.O_RDWR|windows.O_CREAT|windows.O_TRUNC)
}
-// Open opens the named file for reading. If successful, methods on
-// the returned file can be used for reading; the associated file
-// descriptor has mode O_RDONLY.
-// If there is an error, it will be of type *PathError.
+// Open is a copy of [os.Open], modified to use sequential file access.
+//
+// It uses [windows.FILE_FLAG_SEQUENTIAL_SCAN] rather than [windows.FILE_ATTRIBUTE_NORMAL]
+// as implemented in golang. Refer to the [Win32 API documentation] for details
+// on sequential file access.
+//
+// [Win32 API documentation]: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#FILE_FLAG_SEQUENTIAL_SCAN
func Open(name string) (*os.File, error) {
- return OpenFile(name, os.O_RDONLY, 0)
+ return openFileSequential(name, windows.O_RDONLY)
}
-// OpenFile is the generalized open call; most users will use Open
-// or Create instead.
-// If there is an error, it will be of type *PathError.
+// OpenFile is a copy of [os.OpenFile], modified to use sequential file access.
+//
+// It uses [windows.FILE_FLAG_SEQUENTIAL_SCAN] rather than [windows.FILE_ATTRIBUTE_NORMAL]
+// as implemented in golang. Refer to the [Win32 API documentation] for details
+// on sequential file access.
+//
+// [Win32 API documentation]: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#FILE_FLAG_SEQUENTIAL_SCAN
func OpenFile(name string, flag int, _ os.FileMode) (*os.File, error) {
- if name == "" {
- return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOENT}
- }
- r, err := openFileSequential(name, flag, 0)
- if err == nil {
- return r, nil
- }
- return nil, &os.PathError{Op: "open", Path: name, Err: err}
+ return openFileSequential(name, flag)
}
-func openFileSequential(name string, flag int, _ os.FileMode) (file *os.File, err error) {
- r, e := openSequential(name, flag|windows.O_CLOEXEC, 0)
+func openFileSequential(name string, flag int) (file *os.File, err error) {
+ if name == "" {
+ return nil, &os.PathError{Op: "open", Path: name, Err: windows.ERROR_FILE_NOT_FOUND}
+ }
+ r, e := openSequential(name, flag|windows.O_CLOEXEC)
if e != nil {
- return nil, e
+ return nil, &os.PathError{Op: "open", Path: name, Err: e}
}
return os.NewFile(uintptr(r), name), nil
}
@@ -58,7 +62,7 @@ func makeInheritSa() *windows.SecurityAttributes {
return &sa
}
-func openSequential(path string, mode int, _ uint32) (fd windows.Handle, err error) {
+func openSequential(path string, mode int) (fd windows.Handle, err error) {
if len(path) == 0 {
return windows.InvalidHandle, windows.ERROR_FILE_NOT_FOUND
}
@@ -101,15 +105,16 @@ func openSequential(path string, mode int, _ uint32) (fd windows.Handle, err err
createmode = windows.OPEN_EXISTING
}
// Use FILE_FLAG_SEQUENTIAL_SCAN rather than FILE_ATTRIBUTE_NORMAL as implemented in golang.
- // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
- const fileFlagSequentialScan = 0x08000000 // FILE_FLAG_SEQUENTIAL_SCAN
- h, e := windows.CreateFile(pathp, access, sharemode, sa, createmode, fileFlagSequentialScan, 0)
+ // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#FILE_FLAG_SEQUENTIAL_SCAN
+ h, e := windows.CreateFile(pathp, access, sharemode, sa, createmode, windows.FILE_FLAG_SEQUENTIAL_SCAN, 0)
return h, e
}
// Helpers for CreateTemp
-var rand uint32
-var randmu sync.Mutex
+var (
+ rand uint32
+ randmu sync.Mutex
+)
func reseed() uint32 {
return uint32(time.Now().UnixNano() + int64(os.Getpid()))
@@ -127,17 +132,13 @@ func nextSuffix() string {
return strconv.Itoa(int(1e9 + r%1e9))[1:]
}
-// CreateTemp is a copy of os.CreateTemp, modified to use sequential
-// file access. Below is the original comment from golang:
-// TempFile creates a new temporary file in the directory dir
-// with a name beginning with prefix, opens the file for reading
-// and writing, and returns the resulting *os.File.
-// If dir is the empty string, TempFile uses the default directory
-// for temporary files (see os.TempDir).
-// Multiple programs calling TempFile simultaneously
-// will not choose the same file. The caller can use f.Name()
-// to find the pathname of the file. It is the caller's responsibility
-// to remove the file when no longer needed.
+// CreateTemp is a copy of [os.CreateTemp], modified to use sequential file access.
+//
+// It uses [windows.FILE_FLAG_SEQUENTIAL_SCAN] rather than [windows.FILE_ATTRIBUTE_NORMAL]
+// as implemented in golang. Refer to the [Win32 API documentation] for details
+// on sequential file access.
+//
+// [Win32 API documentation]: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#FILE_FLAG_SEQUENTIAL_SCAN
func CreateTemp(dir, prefix string) (f *os.File, err error) {
if dir == "" {
dir = os.TempDir()
@@ -146,7 +147,7 @@ func CreateTemp(dir, prefix string) (f *os.File, err error) {
nconflict := 0
for i := 0; i < 10000; i++ {
name := filepath.Join(dir, prefix+nextSuffix())
- f, err = OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o600)
+ f, err = openFileSequential(name, windows.O_RDWR|windows.O_CREAT|windows.O_EXCL)
if os.IsExist(err) {
if nconflict++; nconflict > 10 {
randmu.Lock()
diff --git a/vendor/github.com/moby/sys/user/idtools.go b/vendor/github.com/moby/sys/user/idtools.go
new file mode 100644
index 0000000..595b7a9
--- /dev/null
+++ b/vendor/github.com/moby/sys/user/idtools.go
@@ -0,0 +1,141 @@
+package user
+
+import (
+ "fmt"
+ "os"
+)
+
+// MkdirOpt is a type for options to pass to Mkdir calls
+type MkdirOpt func(*mkdirOptions)
+
+type mkdirOptions struct {
+ onlyNew bool
+}
+
+// WithOnlyNew is an option for MkdirAllAndChown that will only change ownership and permissions
+// on newly created directories. If the directory already exists, it will not be modified
+func WithOnlyNew(o *mkdirOptions) {
+ o.onlyNew = true
+}
+
+// MkdirAllAndChown creates a directory (include any along the path) and then modifies
+// ownership to the requested uid/gid. By default, if the directory already exists, this
+// function will still change ownership and permissions. If WithOnlyNew is passed as an
+// option, then only the newly created directories will have ownership and permissions changed.
+func MkdirAllAndChown(path string, mode os.FileMode, uid, gid int, opts ...MkdirOpt) error {
+ var options mkdirOptions
+ for _, opt := range opts {
+ opt(&options)
+ }
+
+ return mkdirAs(path, mode, uid, gid, true, options.onlyNew)
+}
+
+// MkdirAndChown creates a directory and then modifies ownership to the requested uid/gid.
+// By default, if the directory already exists, this function still changes ownership and permissions.
+// If WithOnlyNew is passed as an option, then only the newly created directory will have ownership
+// and permissions changed.
+// Note that unlike os.Mkdir(), this function does not return IsExist error
+// in case path already exists.
+func MkdirAndChown(path string, mode os.FileMode, uid, gid int, opts ...MkdirOpt) error {
+ var options mkdirOptions
+ for _, opt := range opts {
+ opt(&options)
+ }
+ return mkdirAs(path, mode, uid, gid, false, options.onlyNew)
+}
+
+// getRootUIDGID retrieves the remapped root uid/gid pair from the set of maps.
+// If the maps are empty, then the root uid/gid will default to "real" 0/0
+func getRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) {
+ uid, err := toHost(0, uidMap)
+ if err != nil {
+ return -1, -1, err
+ }
+ gid, err := toHost(0, gidMap)
+ if err != nil {
+ return -1, -1, err
+ }
+ return uid, gid, nil
+}
+
+// toContainer takes an id mapping, and uses it to translate a
+// host ID to the remapped ID. If no map is provided, then the translation
+// assumes a 1-to-1 mapping and returns the passed in id
+func toContainer(hostID int, idMap []IDMap) (int, error) {
+ if idMap == nil {
+ return hostID, nil
+ }
+ for _, m := range idMap {
+ if (int64(hostID) >= m.ParentID) && (int64(hostID) <= (m.ParentID + m.Count - 1)) {
+ contID := int(m.ID + (int64(hostID) - m.ParentID))
+ return contID, nil
+ }
+ }
+ return -1, fmt.Errorf("host ID %d cannot be mapped to a container ID", hostID)
+}
+
+// toHost takes an id mapping and a remapped ID, and translates the
+// ID to the mapped host ID. If no map is provided, then the translation
+// assumes a 1-to-1 mapping and returns the passed in id #
+func toHost(contID int, idMap []IDMap) (int, error) {
+ if idMap == nil {
+ return contID, nil
+ }
+ for _, m := range idMap {
+ if (int64(contID) >= m.ID) && (int64(contID) <= (m.ID + m.Count - 1)) {
+ hostID := int(m.ParentID + (int64(contID) - m.ID))
+ return hostID, nil
+ }
+ }
+ return -1, fmt.Errorf("container ID %d cannot be mapped to a host ID", contID)
+}
+
+// IdentityMapping contains a mappings of UIDs and GIDs.
+// The zero value represents an empty mapping.
+type IdentityMapping struct {
+ UIDMaps []IDMap `json:"UIDMaps"`
+ GIDMaps []IDMap `json:"GIDMaps"`
+}
+
+// RootPair returns a uid and gid pair for the root user. The error is ignored
+// because a root user always exists, and the defaults are correct when the uid
+// and gid maps are empty.
+func (i IdentityMapping) RootPair() (int, int) {
+ uid, gid, _ := getRootUIDGID(i.UIDMaps, i.GIDMaps)
+ return uid, gid
+}
+
+// ToHost returns the host UID and GID for the container uid, gid.
+// Remapping is only performed if the ids aren't already the remapped root ids
+func (i IdentityMapping) ToHost(uid, gid int) (int, int, error) {
+ var err error
+ ruid, rgid := i.RootPair()
+
+ if uid != ruid {
+ ruid, err = toHost(uid, i.UIDMaps)
+ if err != nil {
+ return ruid, rgid, err
+ }
+ }
+
+ if gid != rgid {
+ rgid, err = toHost(gid, i.GIDMaps)
+ }
+ return ruid, rgid, err
+}
+
+// ToContainer returns the container UID and GID for the host uid and gid
+func (i IdentityMapping) ToContainer(uid, gid int) (int, int, error) {
+ ruid, err := toContainer(uid, i.UIDMaps)
+ if err != nil {
+ return -1, -1, err
+ }
+ rgid, err := toContainer(gid, i.GIDMaps)
+ return ruid, rgid, err
+}
+
+// Empty returns true if there are no id mappings
+func (i IdentityMapping) Empty() bool {
+ return len(i.UIDMaps) == 0 && len(i.GIDMaps) == 0
+}
diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go b/vendor/github.com/moby/sys/user/idtools_unix.go
index 1f11fe4..4e39d24 100644
--- a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go
+++ b/vendor/github.com/moby/sys/user/idtools_unix.go
@@ -1,6 +1,6 @@
//go:build !windows
-package idtools
+package user
import (
"fmt"
@@ -8,11 +8,9 @@ import (
"path/filepath"
"strconv"
"syscall"
-
- "github.com/moby/sys/user"
)
-func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting bool) error {
+func mkdirAs(path string, mode os.FileMode, uid, gid int, mkAll, onlyNew bool) error {
path, err := filepath.Abs(path)
if err != nil {
return err
@@ -23,21 +21,21 @@ func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting
if !stat.IsDir() {
return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR}
}
- if !chownExisting {
+ if onlyNew {
return nil
}
// short-circuit -- we were called with an existing directory and chown was requested
- return setPermissions(path, mode, owner, stat)
+ return setPermissions(path, mode, uid, gid, stat)
}
// make an array containing the original path asked for, plus (for mkAll == true)
// all path components leading up to the complete path that don't exist before we MkdirAll
- // so that we can chown all of them properly at the end. If chownExisting is false, we won't
+ // so that we can chown all of them properly at the end. If onlyNew is true, we won't
// chown the full directory path if it exists
var paths []string
if os.IsNotExist(err) {
- paths = []string{path}
+ paths = append(paths, path)
}
if mkAll {
@@ -49,7 +47,7 @@ func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting
if dirPath == "/" {
break
}
- if _, err = os.Stat(dirPath); err != nil && os.IsNotExist(err) {
+ if _, err = os.Stat(dirPath); os.IsNotExist(err) {
paths = append(paths, dirPath)
}
}
@@ -62,39 +60,18 @@ func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting
// even if it existed, we will chown the requested path + any subpaths that
// didn't exist when we called MkdirAll
for _, pathComponent := range paths {
- if err = setPermissions(pathComponent, mode, owner, nil); err != nil {
+ if err = setPermissions(pathComponent, mode, uid, gid, nil); err != nil {
return err
}
}
return nil
}
-// LookupUser uses traditional local system files lookup (from libcontainer/user) on a username
-//
-// Deprecated: use [user.LookupUser] instead
-func LookupUser(name string) (user.User, error) {
- return user.LookupUser(name)
-}
-
-// LookupUID uses traditional local system files lookup (from libcontainer/user) on a uid
-//
-// Deprecated: use [user.LookupUid] instead
-func LookupUID(uid int) (user.User, error) {
- return user.LookupUid(uid)
-}
-
-// LookupGroup uses traditional local system files lookup (from libcontainer/user) on a group name,
-//
-// Deprecated: use [user.LookupGroup] instead
-func LookupGroup(name string) (user.Group, error) {
- return user.LookupGroup(name)
-}
-
// setPermissions performs a chown/chmod only if the uid/gid don't match what's requested
// Normally a Chown is a no-op if uid/gid match, but in some cases this can still cause an error, e.g. if the
// dir is on an NFS share, so don't call chown unless we absolutely must.
// Likewise for setting permissions.
-func setPermissions(p string, mode os.FileMode, owner Identity, stat os.FileInfo) error {
+func setPermissions(p string, mode os.FileMode, uid, gid int, stat os.FileInfo) error {
if stat == nil {
var err error
stat, err = os.Stat(p)
@@ -108,10 +85,10 @@ func setPermissions(p string, mode os.FileMode, owner Identity, stat os.FileInfo
}
}
ssi := stat.Sys().(*syscall.Stat_t)
- if ssi.Uid == uint32(owner.UID) && ssi.Gid == uint32(owner.GID) {
+ if ssi.Uid == uint32(uid) && ssi.Gid == uint32(gid) {
return nil
}
- return os.Chown(p, owner.UID, owner.GID)
+ return os.Chown(p, uid, gid)
}
// LoadIdentityMapping takes a requested username and
@@ -119,9 +96,9 @@ func setPermissions(p string, mode os.FileMode, owner Identity, stat os.FileInfo
// proper uid and gid remapping ranges for that user/group pair
func LoadIdentityMapping(name string) (IdentityMapping, error) {
// TODO: Consider adding support for calling out to "getent"
- usr, err := user.LookupUser(name)
+ usr, err := LookupUser(name)
if err != nil {
- return IdentityMapping{}, fmt.Errorf("could not get user for username %s: %v", name, err)
+ return IdentityMapping{}, fmt.Errorf("could not get user for username %s: %w", name, err)
}
subuidRanges, err := lookupSubRangesFile("/etc/subuid", usr)
@@ -139,9 +116,9 @@ func LoadIdentityMapping(name string) (IdentityMapping, error) {
}, nil
}
-func lookupSubRangesFile(path string, usr user.User) ([]IDMap, error) {
+func lookupSubRangesFile(path string, usr User) ([]IDMap, error) {
uidstr := strconv.Itoa(usr.Uid)
- rangeList, err := user.ParseSubIDFileFilter(path, func(sid user.SubID) bool {
+ rangeList, err := ParseSubIDFileFilter(path, func(sid SubID) bool {
return sid.Name == usr.Name || sid.Name == uidstr
})
if err != nil {
@@ -153,14 +130,14 @@ func lookupSubRangesFile(path string, usr user.User) ([]IDMap, error) {
idMap := []IDMap{}
- containerID := 0
+ var containerID int64
for _, idrange := range rangeList {
idMap = append(idMap, IDMap{
- ContainerID: containerID,
- HostID: int(idrange.SubID),
- Size: int(idrange.Count),
+ ID: containerID,
+ ParentID: idrange.SubID,
+ Count: idrange.Count,
})
- containerID = containerID + int(idrange.Count)
+ containerID = containerID + idrange.Count
}
return idMap, nil
}
diff --git a/vendor/github.com/moby/sys/user/idtools_windows.go b/vendor/github.com/moby/sys/user/idtools_windows.go
new file mode 100644
index 0000000..9de730c
--- /dev/null
+++ b/vendor/github.com/moby/sys/user/idtools_windows.go
@@ -0,0 +1,13 @@
+package user
+
+import (
+ "os"
+)
+
+// This is currently a wrapper around [os.MkdirAll] since currently
+// permissions aren't set through this path, the identity isn't utilized.
+// Ownership is handled elsewhere, but in the future could be support here
+// too.
+func mkdirAs(path string, _ os.FileMode, _, _ int, _, _ bool) error {
+ return os.MkdirAll(path, 0)
+}
diff --git a/vendor/github.com/moby/sys/user/user.go b/vendor/github.com/moby/sys/user/user.go
index 984466d..198c493 100644
--- a/vendor/github.com/moby/sys/user/user.go
+++ b/vendor/github.com/moby/sys/user/user.go
@@ -197,7 +197,6 @@ func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
for {
var line []byte
line, isPrefix, err = rd.ReadLine()
-
if err != nil {
// We should return no error if EOF is reached
// without a match.
diff --git a/vendor/github.com/moby/term/term_unix.go b/vendor/github.com/moby/term/term_unix.go
index 2ec7706..579ce55 100644
--- a/vendor/github.com/moby/term/term_unix.go
+++ b/vendor/github.com/moby/term/term_unix.go
@@ -81,7 +81,7 @@ func setRawTerminal(fd uintptr) (*State, error) {
return makeRaw(fd)
}
-func setRawTerminalOutput(fd uintptr) (*State, error) {
+func setRawTerminalOutput(uintptr) (*State, error) {
return nil, nil
}
diff --git a/vendor/github.com/playwright-community/playwright-go/.gitattributes b/vendor/github.com/playwright-community/playwright-go/.gitattributes
new file mode 100644
index 0000000..c976050
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/.gitattributes
@@ -0,0 +1,3 @@
+# text files must be lf for golden file tests to work
+* text=auto eol=lf
+
diff --git a/vendor/github.com/playwright-community/playwright-go/.gitignore b/vendor/github.com/playwright-community/playwright-go/.gitignore
new file mode 100644
index 0000000..83e2355
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/.gitignore
@@ -0,0 +1,34 @@
+# Created by https://www.toptal.com/developers/gitignore/api/go
+# Edit at https://www.toptal.com/developers/gitignore?templates=go
+
+### Go ###
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Dependency directories (remove the comment below to include it)
+# vendor/
+
+### Go Patch ###
+/vendor/
+/Godeps/
+
+# End of https://www.toptal.com/developers/gitignore/api/go
+covprofile
+.idea/
+.DS_Store
+
+api.json
+_site/
+.jekyll-cache/
+
+.vscode/settings.json \ No newline at end of file
diff --git a/vendor/github.com/playwright-community/playwright-go/.gitmodules b/vendor/github.com/playwright-community/playwright-go/.gitmodules
new file mode 100644
index 0000000..9ab899d
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "playwright"]
+ path = playwright
+ url = https://github.com/microsoft/playwright
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 0000000..1557a3f
--- /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/.nojekyll b/vendor/github.com/playwright-community/playwright-go/.nojekyll
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/.nojekyll
diff --git a/vendor/github.com/playwright-community/playwright-go/404.html b/vendor/github.com/playwright-community/playwright-go/404.html
new file mode 100644
index 0000000..086a5c9
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/404.html
@@ -0,0 +1,25 @@
+---
+permalink: /404.html
+layout: default
+---
+
+<style type="text/css" media="screen">
+ .container {
+ margin: 10px auto;
+ max-width: 600px;
+ text-align: center;
+ }
+ h1 {
+ margin: 30px 0;
+ font-size: 4em;
+ line-height: 1;
+ letter-spacing: -1px;
+ }
+</style>
+
+<div class="container">
+ <h1>404</h1>
+
+ <p><strong>Page not found :(</strong></p>
+ <p>The requested page could not be found.</p>
+</div>
diff --git a/vendor/github.com/playwright-community/playwright-go/CONTRIBUTING.md b/vendor/github.com/playwright-community/playwright-go/CONTRIBUTING.md
new file mode 100644
index 0000000..3b11995
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/CONTRIBUTING.md
@@ -0,0 +1,39 @@
+# 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
+
+For every Pull Request on GitHub and on the main branch the coverage data will get sent over to [Coveralls](https://coveralls.io/github/playwright-community/playwright-go), this is helpful for finding functions that aren't covered by tests.
+
+### Running tests
+
+You can use the `BROWSER` environment variable to use a different browser than Chromium for the tests and use the `HEADLESS` environment variable which is useful for debugging.
+
+```
+BROWSER=chromium HEADLESS=1 go test -v --race ./...
+```
+
+### Roll
+
+1. Find out to which upstream version you want to roll, and change the value of `playwrightCliVersion` in the **run.go** to the new version.
+1. Download current version of Playwright driver `go run scripts/install-browsers/main.go`
+1. Apply patch `bash scripts/apply-patch.sh`
+1. Fix merge conflicts if any, otherwise ignore this step. Once you are happy you can commit the changes `cd playwright; git commit -am "apply patch" && cd ..`
+1. Regenerate a new patch `bash scripts/update-patch.sh`
+1. Generate go code `go generate ./...`
+
+To adapt to the new version of Playwright's protocol and feature updates, you may need to modify the patch. Refer to the following steps:
+
+1. Apply patch `bash scripts/apply-patch.sh`
+1. `cd playwright`
+1. Revert the patch`git reset HEAD~1`
+1. Modify the files under `docs/src/api`, etc. as needed. Available references:
+ - Protocol `packages/protocol/src/protocol.yml`
+ - [Playwright python](https://github.com/microsoft/playwright-python)
+1. Commit the changes `git commit -am "apply patch"`
+1. Regenerate a new patch `bash scripts/update-patch.sh`
+1. Generate go code `go generate ./...`.
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 0000000..3077cf3
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/Dockerfile.example
@@ -0,0 +1,25 @@
+# Stage 1: Modules caching
+FROM golang:1.22 as modules
+COPY go.mod go.sum /modules/
+WORKDIR /modules
+RUN go mod download
+
+# Stage 2: Build
+FROM golang:1.22 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:noble
+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/LICENSE b/vendor/github.com/playwright-community/playwright-go/LICENSE
new file mode 100644
index 0000000..d4f29b3
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Max Schmitt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/playwright-community/playwright-go/README.md b/vendor/github.com/playwright-community/playwright-go/README.md
new file mode 100644
index 0000000..a9e3dd7
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/README.md
@@ -0,0 +1,148 @@
+# 🎭 [Playwright](https://github.com/microsoft/playwright#readme) for <img src="https://user-images.githubusercontent.com/17984549/91302719-343a1d80-e7a7-11ea-8d6a-9448ef598420.png" height="35" />
+
+## Looking for maintainers and see [here](https://github.com/playwright-community/playwright-go/issues/122). Thanks!
+
+[![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) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-136.0.7103.25-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-137.0-blue.svg?logo=mozilla-firefox)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-18.4-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop -->
+
+[API reference](https://playwright.dev/docs/api/class-playwright) | [Example recipes](https://github.com/playwright-community/playwright-go/tree/main/examples)
+
+Playwright is a Go library to automate [Chromium](https://www.chromium.org/Home), [Firefox](https://www.mozilla.org/en-US/firefox/new/) and [WebKit](https://webkit.org/) with a single API. Playwright is built to enable cross-browser web automation that is **ever-green**, **capable**, **reliable** and **fast**.
+
+| | Linux | macOS | Windows |
+| :--- | :---: | :---: | :---: |
+| Chromium <!-- GEN:chromium-version -->136.0.7103.25<!-- GEN:stop --> | ✅ | ✅ | ✅ |
+| WebKit <!-- GEN:webkit-version -->18.4<!-- GEN:stop --> | ✅ | ✅ | ✅ |
+| Firefox <!-- GEN:firefox-version -->137.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
+
+Headless execution is supported for all the browsers on all platforms.
+
+## Installation
+
+```txt
+go get -u github.com/playwright-community/playwright-go
+```
+
+Install the browsers and OS dependencies:
+
+```bash
+go run github.com/playwright-community/playwright-go/cmd/playwright@latest install --with-deps
+# Or
+go install github.com/playwright-community/playwright-go/cmd/playwright@latest
+playwright install --with-deps
+```
+
+Alternatively you can do it inside your program via which downloads the driver and browsers:
+
+```go
+err := playwright.Install()
+```
+
+## Capabilities
+
+Playwright is built to automate the broad and growing set of web browser capabilities used by Single Page Apps and Progressive Web Apps.
+
+* Scenarios that span multiple page, domains and iframes
+* Auto-wait for elements to be ready before executing actions (like click, fill)
+* Intercept network activity for stubbing and mocking network requests
+* Emulate mobile devices, geolocation, permissions
+* Support for web components via shadow-piercing selectors
+* Native input events for mouse and keyboard
+* Upload and download files
+
+## Example
+
+The following example crawls the current top voted items from [Hacker News](https://news.ycombinator.com).
+
+```go
+
+package main
+
+import (
+ "fmt"
+ "log"
+
+ "github.com/playwright-community/playwright-go"
+)
+
+func main() {
+ pw, err := playwright.Run()
+ if err != nil {
+ log.Fatalf("could not start playwright: %v", err)
+ }
+ browser, err := pw.Chromium.Launch()
+ if err != nil {
+ log.Fatalf("could not launch browser: %v", err)
+ }
+ page, err := browser.NewPage()
+ if err != nil {
+ log.Fatalf("could not create page: %v", err)
+ }
+ if _, err = page.Goto("https://news.ycombinator.com"); err != nil {
+ log.Fatalf("could not goto: %v", err)
+ }
+ entries, err := page.Locator(".athing").All()
+ if err != nil {
+ log.Fatalf("could not get entries: %v", err)
+ }
+ for i, entry := range entries {
+ title, err := entry.Locator("td.title > span > a").TextContent()
+ if err != nil {
+ log.Fatalf("could not get text content: %v", err)
+ }
+ fmt.Printf("%d: %s\n", i+1, title)
+ }
+ if err = browser.Close(); err != nil {
+ log.Fatalf("could not close browser: %v", err)
+ }
+ if err = pw.Stop(); err != nil {
+ log.Fatalf("could not stop Playwright: %v", err)
+ }
+}
+```
+
+## 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)
+* [Emulate mobile and geolocation](./examples/mobile-and-geolocation/main.go)
+* [Parallel scraping using a WaitGroup](./examples/parallel-scraping/main.go)
+* [Rendering a PDF of a website](./examples/pdf/main.go)
+* [Scraping HackerNews](./examples/scraping/main.go)
+* [Take a screenshot](./examples/screenshot/main.go)
+* [Record a video](./examples/video/main.go)
+* [Monitor network activity](./examples/network-monitoring/main.go)
+
+## How does it work?
+
+Playwright is a Node.js library which uses:
+
+* Chrome DevTools Protocol to communicate with Chromium
+* Patched Firefox to communicate with Firefox
+* Patched WebKit to communicate with WebKit
+
+These patches are based on the original sources of the browsers and don't modify the browser behaviour so the browsers are basically the same (see [here](https://github.com/microsoft/playwright/tree/main/browser_patches)) as you see them in the wild. The support for different programming languages is based on exposing a RPC server in the Node.js land which can be used to allow other languages to use Playwright without implementing all the custom logic:
+
+* [Playwright for Python](https://github.com/microsoft/playwright-python)
+* [Playwright for .NET](https://github.com/microsoft/playwright-sharp)
+* [Playwright for Java](https://github.com/microsoft/playwright-java)
+* [Playwright for Go](https://github.com/playwright-community/playwright-go)
+
+The bridge between Node.js and the other languages is basically a Node.js runtime combined with Playwright which gets shipped for each of these languages (around 50MB) and then communicates over stdio to send the relevant commands. This will also download the pre-compiled browsers.
+
+## Is Playwright for Go ready?
+
+We are ready for your feedback, but we are still covering Playwright Go with the tests.
+
+## Resources
+
+* [Playwright for Go Documentation](https://pkg.go.dev/github.com/playwright-community/playwright-go)
+* [Playwright Documentation](https://playwright.dev/docs/api/class-playwright)
+* [Example recipes](https://github.com/playwright-community/playwright-go/tree/main/examples)
diff --git a/vendor/github.com/playwright-community/playwright-go/_config.yml b/vendor/github.com/playwright-community/playwright-go/_config.yml
new file mode 100644
index 0000000..15ec3b2
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/_config.yml
@@ -0,0 +1,21 @@
+title: Playwright for Go
+email: max@schmitt.mx
+description: >- # this means to ignore newlines until "baseurl:"
+ Playwright is a Node.js library to automate Chromium, Firefox and WebKit with a single API.
+ Playwright is built to enable cross-browser web automation that is ever-green, capable, reliable and fast.
+baseurl: "/playwright-go"
+url: "https://playwright-community.github.io/"
+twitter_username: maxibanki
+github_username: playwright-community
+remote_theme: pages-themes/cayman@v0.2.0
+plugins:
+ - jekyll-remote-theme
+ - jekyll-optional-front-matter
+ - jekyll-readme-index
+exclude:
+ - playwright/
+defaults:
+ - scope:
+ path: "" # an empty string here means all files in the project
+ values:
+ layout: "default"
diff --git a/vendor/github.com/playwright-community/playwright-go/apiresponse_assertions.go b/vendor/github.com/playwright-community/playwright-go/apiresponse_assertions.go
new file mode 100644
index 0000000..187618e
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/apiresponse_assertions.go
@@ -0,0 +1,75 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+ "regexp"
+ "strings"
+)
+
+type apiResponseAssertionsImpl struct {
+ actual APIResponse
+ isNot bool
+}
+
+func newAPIResponseAssertions(actual APIResponse, isNot bool) *apiResponseAssertionsImpl {
+ return &apiResponseAssertionsImpl{
+ actual: actual,
+ isNot: isNot,
+ }
+}
+
+func (ar *apiResponseAssertionsImpl) Not() APIResponseAssertions {
+ return newAPIResponseAssertions(ar.actual, true)
+}
+
+func (ar *apiResponseAssertionsImpl) ToBeOK() error {
+ if ar.isNot != ar.actual.Ok() {
+ return nil
+ }
+ message := fmt.Sprintf(`Response status expected to be within [200..299] range, was %v`, ar.actual.Status())
+ if ar.isNot {
+ message = strings.ReplaceAll(message, "expected to", "expected not to")
+ }
+ logList, err := ar.actual.(*apiResponseImpl).fetchLog()
+ if err != nil {
+ return err
+ }
+ log := strings.Join(logList, "\n")
+ if log != "" {
+ message += "\nCall log:\n" + log
+ }
+
+ isTextEncoding := false
+ contentType, ok := ar.actual.Headers()["content-type"]
+ if ok {
+ isTextEncoding = isTexualMimeType(contentType)
+ }
+ if isTextEncoding {
+ text, err := ar.actual.Text()
+ if err == nil {
+ message += fmt.Sprintf(`\n Response Text:\n %s`, subString(text, 0, 1000))
+ }
+ }
+ return errors.New(message)
+}
+
+func isTexualMimeType(mimeType string) bool {
+ re := regexp.MustCompile(`^(text\/.*?|application\/(json|(x-)?javascript|xml.*?|ecmascript|graphql|x-www-form-urlencoded)|image\/svg(\+xml)?|application\/.*?(\+json|\+xml))(;\s*charset=.*)?$`)
+ return re.MatchString(mimeType)
+}
+
+func subString(s string, start, length int) string {
+ if start < 0 {
+ start = 0
+ }
+ if length < 0 {
+ length = 0
+ }
+ rs := []rune(s)
+ end := start + length
+ if end > len(rs) {
+ end = len(rs)
+ }
+ return string(rs[start:end])
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/artifact.go b/vendor/github.com/playwright-community/playwright-go/artifact.go
new file mode 100644
index 0000000..c76b892
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/artifact.go
@@ -0,0 +1,70 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+)
+
+type artifactImpl struct {
+ channelOwner
+}
+
+func (a *artifactImpl) AbsolutePath() string {
+ return a.initializer["absolutePath"].(string)
+}
+
+func (a *artifactImpl) PathAfterFinished() (string, error) {
+ if a.connection.isRemote {
+ return "", errors.New("Path is not available when connecting remotely. Use SaveAs() to save a local copy")
+ }
+ path, err := a.channel.Send("pathAfterFinished")
+ return path.(string), err
+}
+
+func (a *artifactImpl) SaveAs(path string) error {
+ if !a.connection.isRemote {
+ _, err := a.channel.Send("saveAs", map[string]interface{}{
+ "path": path,
+ })
+ return err
+ }
+ streamChannel, err := a.channel.Send("saveAsStream")
+ if err != nil {
+ return err
+ }
+ stream := fromChannel(streamChannel).(*streamImpl)
+ return stream.SaveAs(path)
+}
+
+func (a *artifactImpl) Failure() error {
+ reason, err := a.channel.Send("failure")
+ if reason == nil {
+ return err
+ }
+ return fmt.Errorf("%w: %v", ErrPlaywright, reason)
+}
+
+func (a *artifactImpl) Delete() error {
+ _, err := a.channel.Send("delete")
+ return err
+}
+
+func (a *artifactImpl) Cancel() error {
+ _, err := a.channel.Send("cancel")
+ return err
+}
+
+func (a *artifactImpl) ReadIntoBuffer() ([]byte, error) {
+ streamChannel, err := a.channel.Send("stream")
+ if err != nil {
+ return nil, err
+ }
+ stream := fromChannel(streamChannel)
+ return stream.(*streamImpl).ReadAll()
+}
+
+func newArtifact(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *artifactImpl {
+ artifact := &artifactImpl{}
+ artifact.createChannelOwner(artifact, parent, objectType, guid, initializer)
+ return artifact
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/assertions.go b/vendor/github.com/playwright-community/playwright-go/assertions.go
new file mode 100644
index 0000000..5e0e710
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/assertions.go
@@ -0,0 +1,146 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "regexp"
+ "strings"
+)
+
+const assertionsDefaultTimeout = 5000 // 5s
+
+type playwrightAssertionsImpl struct {
+ defaultTimeout *float64
+}
+
+// NewPlaywrightAssertions creates a new instance of PlaywrightAssertions
+// - timeout: default value is 5000 (ms)
+func NewPlaywrightAssertions(timeout ...float64) PlaywrightAssertions {
+ if len(timeout) > 0 {
+ return &playwrightAssertionsImpl{Float(timeout[0])}
+ }
+ return &playwrightAssertionsImpl{Float(assertionsDefaultTimeout)}
+}
+
+func (pa *playwrightAssertionsImpl) APIResponse(response APIResponse) APIResponseAssertions {
+ return newAPIResponseAssertions(response, false)
+}
+
+func (pa *playwrightAssertionsImpl) Locator(locator Locator) LocatorAssertions {
+ return newLocatorAssertions(locator, false, pa.defaultTimeout)
+}
+
+func (pa *playwrightAssertionsImpl) Page(page Page) PageAssertions {
+ return newPageAssertions(page, false, pa.defaultTimeout)
+}
+
+type expectedTextValue struct {
+ Str *string `json:"string,omitempty"`
+ RegexSource *string `json:"regexSource,omitempty"`
+ RegexFlags *string `json:"regexFlags,omitempty"`
+ MatchSubstring *bool `json:"matchSubstring,omitempty"`
+ IgnoreCase *bool `json:"ignoreCase,omitempty"`
+ NormalizeWhiteSpace *bool `json:"normalizeWhiteSpace,omitempty"`
+}
+
+type frameExpectOptions struct {
+ ExpressionArg interface{} `json:"expressionArg,omitempty"`
+ ExpectedText []expectedTextValue `json:"expectedText,omitempty"`
+ ExpectedNumber *float64 `json:"expectedNumber,omitempty"`
+ ExpectedValue interface{} `json:"expectedValue,omitempty"`
+ UseInnerText *bool `json:"useInnerText,omitempty"`
+ IsNot bool `json:"isNot"`
+ Timeout *float64 `json:"timeout"`
+}
+
+type frameExpectResult struct {
+ Matches bool `json:"matches"`
+ Received interface{} `json:"received,omitempty"`
+ TimedOut *bool `json:"timedOut,omitempty"`
+ Log []string `json:"log,omitempty"`
+}
+
+type assertionsBase struct {
+ actualLocator Locator
+ isNot bool
+ defaultTimeout *float64
+}
+
+func (b *assertionsBase) expect(
+ expression string,
+ options frameExpectOptions,
+ expected interface{},
+ message string,
+) error {
+ options.IsNot = b.isNot
+ if options.Timeout == nil {
+ options.Timeout = b.defaultTimeout
+ }
+ if options.IsNot {
+ message = strings.ReplaceAll(message, "expected to", "expected not to")
+ }
+ result, err := b.actualLocator.(*locatorImpl).expect(expression, options)
+ if err != nil {
+ return err
+ }
+
+ if result.Matches == b.isNot {
+ actual := result.Received
+ log := strings.Join(result.Log, "\n")
+ if log != "" {
+ log = "\nCall log:\n" + log
+ }
+ if expected != nil {
+ return fmt.Errorf("%s '%v'\nActual value: %v %s", message, expected, actual, log)
+ }
+ return fmt.Errorf("%s\nActual value: %v %s", message, actual, log)
+ }
+
+ return nil
+}
+
+func toExpectedTextValues(
+ items []interface{},
+ matchSubstring bool,
+ normalizeWhiteSpace bool,
+ ignoreCase *bool,
+) ([]expectedTextValue, error) {
+ var out []expectedTextValue
+ for _, item := range items {
+ switch item := item.(type) {
+ case string:
+ out = append(out, expectedTextValue{
+ Str: String(item),
+ MatchSubstring: Bool(matchSubstring),
+ NormalizeWhiteSpace: Bool(normalizeWhiteSpace),
+ IgnoreCase: ignoreCase,
+ })
+ case *regexp.Regexp:
+ pattern, flags := convertRegexp(item)
+ out = append(out, expectedTextValue{
+ RegexSource: String(pattern),
+ RegexFlags: String(flags),
+ MatchSubstring: Bool(matchSubstring),
+ NormalizeWhiteSpace: Bool(normalizeWhiteSpace),
+ IgnoreCase: ignoreCase,
+ })
+ default:
+ return nil, errors.New("value must be a string or regexp")
+ }
+ }
+ return out, nil
+}
+
+func convertToInterfaceList(v interface{}) []interface{} {
+ rv := reflect.ValueOf(v)
+ if rv.Kind() != reflect.Slice {
+ return []interface{}{v}
+ }
+
+ list := make([]interface{}, rv.Len())
+ for i := 0; i < rv.Len(); i++ {
+ list[i] = rv.Index(i).Interface()
+ }
+ return list
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/binding_call.go b/vendor/github.com/playwright-community/playwright-go/binding_call.go
new file mode 100644
index 0000000..8468992
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/binding_call.go
@@ -0,0 +1,87 @@
+package playwright
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/go-stack/stack"
+)
+
+type BindingCall interface {
+ Call(f BindingCallFunction)
+}
+
+type bindingCallImpl struct {
+ channelOwner
+}
+
+// BindingSource is the value passed to a binding call execution
+type BindingSource struct {
+ Context BrowserContext
+ Page Page
+ Frame Frame
+}
+
+// ExposedFunction represents the func signature of an exposed function
+type ExposedFunction = func(args ...interface{}) interface{}
+
+// BindingCallFunction represents the func signature of an exposed binding call func
+type BindingCallFunction func(source *BindingSource, args ...interface{}) interface{}
+
+func (b *bindingCallImpl) Call(f BindingCallFunction) {
+ defer func() {
+ if r := recover(); r != nil {
+ if _, err := b.channel.Send("reject", map[string]interface{}{
+ "error": serializeError(r.(error)),
+ }); err != nil {
+ logger.Error("could not reject BindingCall", "error", err)
+ }
+ }
+ }()
+
+ frame := fromChannel(b.initializer["frame"]).(*frameImpl)
+ source := &BindingSource{
+ Context: frame.Page().Context(),
+ Page: frame.Page(),
+ Frame: frame,
+ }
+ var result interface{}
+ if handle, ok := b.initializer["handle"]; ok {
+ result = f(source, fromChannel(handle))
+ } else {
+ initializerArgs := b.initializer["args"].([]interface{})
+ funcArgs := []interface{}{}
+ for i := 0; i < len(initializerArgs); i++ {
+ funcArgs = append(funcArgs, parseResult(initializerArgs[i]))
+ }
+ result = f(source, funcArgs...)
+ }
+ _, err := b.channel.Send("resolve", map[string]interface{}{
+ "result": serializeArgument(result),
+ })
+ if err != nil {
+ logger.Error("could not resolve BindingCall", "error", 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"),
+ },
+ }
+}
+
+func newBindingCall(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *bindingCallImpl {
+ bt := &bindingCallImpl{}
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/browser.go b/vendor/github.com/playwright-community/playwright-go/browser.go
new file mode 100644
index 0000000..c87540a
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/browser.go
@@ -0,0 +1,274 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+)
+
+type browserImpl struct {
+ channelOwner
+ isConnected bool
+ shouldCloseConnectionOnClose bool
+ contexts []BrowserContext
+ browserType BrowserType
+ chromiumTracingPath *string
+ closeReason *string
+}
+
+func (b *browserImpl) BrowserType() BrowserType {
+ return b.browserType
+}
+
+func (b *browserImpl) IsConnected() bool {
+ b.RLock()
+ defer b.RUnlock()
+ return b.isConnected
+}
+
+func (b *browserImpl) NewContext(options ...BrowserNewContextOptions) (BrowserContext, error) {
+ overrides := map[string]interface{}{}
+ option := BrowserNewContextOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ if option.AcceptDownloads != nil {
+ if *option.AcceptDownloads {
+ overrides["acceptDownloads"] = "accept"
+ } else {
+ overrides["acceptDownloads"] = "deny"
+ }
+ options[0].AcceptDownloads = nil
+ }
+ if option.ExtraHttpHeaders != nil {
+ 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)
+ if err != nil {
+ return nil, fmt.Errorf("could not read storage state file: %w", err)
+ }
+ err = json.Unmarshal(storageString, &storageState)
+ if err != nil {
+ return nil, fmt.Errorf("could not parse storage state file: %w", err)
+ }
+ options[0].StorageState = storageState
+ options[0].StorageStatePath = nil
+ }
+ if option.NoViewport != nil && *options[0].NoViewport {
+ overrides["noDefaultViewport"] = true
+ options[0].NoViewport = nil
+ }
+ if option.RecordHarPath != nil {
+ overrides["recordHar"] = prepareRecordHarOptions(recordHarInputOptions{
+ Path: *options[0].RecordHarPath,
+ URL: options[0].RecordHarURLFilter,
+ Mode: options[0].RecordHarMode,
+ Content: options[0].RecordHarContent,
+ OmitContent: options[0].RecordHarOmitContent,
+ })
+ options[0].RecordHarPath = nil
+ options[0].RecordHarURLFilter = nil
+ options[0].RecordHarMode = nil
+ options[0].RecordHarContent = nil
+ options[0].RecordHarOmitContent = nil
+ }
+ channel, err := b.channel.Send("newContext", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ context := fromChannel(channel).(*browserContextImpl)
+ context.browser = b
+ b.browserType.(*browserTypeImpl).didCreateContext(context, &option, nil)
+ return context, nil
+}
+
+func (b *browserImpl) NewPage(options ...BrowserNewPageOptions) (Page, error) {
+ opts := make([]BrowserNewContextOptions, 0)
+ if len(options) == 1 {
+ opts = append(opts, BrowserNewContextOptions(options[0]))
+ }
+ context, err := b.NewContext(opts...)
+ if err != nil {
+ return nil, err
+ }
+ page, err := context.NewPage()
+ if err != nil {
+ return nil, err
+ }
+ page.(*pageImpl).ownedContext = context
+ context.(*browserContextImpl).ownedPage = page
+ return page, nil
+}
+
+func (b *browserImpl) NewBrowserCDPSession() (CDPSession, error) {
+ channel, err := b.channel.Send("newBrowserCDPSession")
+ if err != nil {
+ return nil, err
+ }
+
+ cdpSession := fromChannel(channel).(*cdpSessionImpl)
+
+ return cdpSession, nil
+}
+
+func (b *browserImpl) Contexts() []BrowserContext {
+ b.Lock()
+ defer b.Unlock()
+ return b.contexts
+}
+
+func (b *browserImpl) Close(options ...BrowserCloseOptions) (err error) {
+ if len(options) == 1 {
+ b.closeReason = options[0].Reason
+ }
+
+ if b.shouldCloseConnectionOnClose {
+ 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
+}
+
+func (b *browserImpl) Version() string {
+ return b.initializer["version"].(string)
+}
+
+func (b *browserImpl) StartTracing(options ...BrowserStartTracingOptions) error {
+ overrides := map[string]interface{}{}
+ option := BrowserStartTracingOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ if option.Page != nil {
+ overrides["page"] = option.Page.(*pageImpl).channel
+ option.Page = nil
+ }
+ if option.Path != nil {
+ b.chromiumTracingPath = option.Path
+ option.Path = nil
+ }
+ _, err := b.channel.Send("startTracing", option, overrides)
+ return err
+}
+
+func (b *browserImpl) StopTracing() ([]byte, error) {
+ channel, err := b.channel.Send("stopTracing")
+ if err != nil {
+ return nil, err
+ }
+ artifact := fromChannel(channel).(*artifactImpl)
+ binary, err := artifact.ReadIntoBuffer()
+ if err != nil {
+ return nil, err
+ }
+ err = artifact.Delete()
+ if err != nil {
+ return binary, err
+ }
+ if b.chromiumTracingPath != nil {
+ err := os.MkdirAll(filepath.Dir(*b.chromiumTracingPath), 0o777)
+ if err != nil {
+ return binary, err
+ }
+ err = os.WriteFile(*b.chromiumTracingPath, binary, 0o644)
+ if err != nil {
+ return binary, err
+ }
+ }
+ return binary, nil
+}
+
+func (b *browserImpl) onClose() {
+ b.Lock()
+ if b.isConnected {
+ b.isConnected = false
+ b.Unlock()
+ b.Emit("disconnected", b)
+ return
+ }
+ b.Unlock()
+}
+
+func (b *browserImpl) OnDisconnected(fn func(Browser)) {
+ b.On("disconnected", fn)
+}
+
+func newBrowser(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *browserImpl {
+ b := &browserImpl{
+ isConnected: true,
+ contexts: make([]BrowserContext, 0),
+ }
+ b.createChannelOwner(b, parent, objectType, guid, initializer)
+ // convert parent to *browserTypeImpl
+ b.browserType = newBrowserType(parent.parent, parent.objectType, parent.guid, parent.initializer)
+ 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
new file mode 100644
index 0000000..1d420d3
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/browser_context.go
@@ -0,0 +1,914 @@
+package playwright
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "os"
+ "regexp"
+ "slices"
+ "strings"
+ "sync"
+
+ "github.com/playwright-community/playwright-go/internal/safe"
+)
+
+type browserContextImpl struct {
+ channelOwner
+ timeoutSettings *timeoutSettings
+ closeWasCalled bool
+ options *BrowserNewContextOptions
+ pages []Page
+ routes []*routeHandlerEntry
+ webSocketRoutes []*webSocketRouteHandler
+ 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.setDefaultNavigationTimeoutImpl(&timeout)
+}
+
+func (b *browserContextImpl) setDefaultNavigationTimeoutImpl(timeout *float64) {
+ b.timeoutSettings.SetDefaultNavigationTimeout(timeout)
+ b.channel.SendNoReplyInternal("setDefaultNavigationTimeoutNoReply", map[string]interface{}{
+ "timeout": timeout,
+ })
+}
+
+func (b *browserContextImpl) SetDefaultTimeout(timeout float64) {
+ b.setDefaultTimeoutImpl(&timeout)
+}
+
+func (b *browserContextImpl) setDefaultTimeoutImpl(timeout *float64) {
+ b.timeoutSettings.SetDefaultTimeout(timeout)
+ b.channel.SendNoReplyInternal("setDefaultTimeoutNoReply", map[string]interface{}{
+ "timeout": timeout,
+ })
+}
+
+func (b *browserContextImpl) Pages() []Page {
+ b.Lock()
+ defer b.Unlock()
+ return b.pages
+}
+
+func (b *browserContextImpl) Browser() Browser {
+ return b.browser
+}
+
+func (b *browserContextImpl) Tracing() Tracing {
+ return b.tracing
+}
+
+func (b *browserContextImpl) NewCDPSession(page interface{}) (CDPSession, error) {
+ params := map[string]interface{}{}
+
+ if p, ok := page.(*pageImpl); ok {
+ params["page"] = p.channel
+ } else if f, ok := page.(*frameImpl); ok {
+ params["frame"] = f.channel
+ } else {
+ return nil, fmt.Errorf("not page or frame: %v", page)
+ }
+
+ channel, err := b.channel.Send("newCDPSession", params)
+ if err != nil {
+ return nil, err
+ }
+
+ cdpSession := fromChannel(channel).(*cdpSessionImpl)
+
+ return cdpSession, nil
+}
+
+func (b *browserContextImpl) NewPage() (Page, error) {
+ if b.ownedPage != nil {
+ return nil, errors.New("Please use browser.NewContext()")
+ }
+ channel, err := b.channel.Send("newPage")
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(channel).(*pageImpl), nil
+}
+
+func (b *browserContextImpl) Cookies(urls ...string) ([]Cookie, error) {
+ result, err := b.channel.Send("cookies", map[string]interface{}{
+ "urls": urls,
+ })
+ if err != nil {
+ return nil, err
+ }
+ cookies := make([]Cookie, len(result.([]interface{})))
+ for i, item := range result.([]interface{}) {
+ cookie := &Cookie{}
+ remapMapToStruct(item, cookie)
+ cookies[i] = *cookie
+ }
+ return cookies, nil
+}
+
+func (b *browserContextImpl) AddCookies(cookies []OptionalCookie) error {
+ _, err := b.channel.Send("addCookies", map[string]interface{}{
+ "cookies": cookies,
+ })
+ return err
+}
+
+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
+}
+
+func (b *browserContextImpl) GrantPermissions(permissions []string, options ...BrowserContextGrantPermissionsOptions) error {
+ _, err := b.channel.Send("grantPermissions", map[string]interface{}{
+ "permissions": permissions,
+ }, options)
+ return err
+}
+
+func (b *browserContextImpl) ClearPermissions() error {
+ _, err := b.channel.Send("clearPermissions")
+ return err
+}
+
+func (b *browserContextImpl) SetGeolocation(geolocation *Geolocation) error {
+ _, err := b.channel.Send("setGeolocation", map[string]interface{}{
+ "geolocation": geolocation,
+ })
+ return err
+}
+
+func (b *browserContextImpl) ResetGeolocation() error {
+ _, err := b.channel.Send("setGeolocation", map[string]interface{}{})
+ return err
+}
+
+func (b *browserContextImpl) SetExtraHTTPHeaders(headers map[string]string) error {
+ _, err := b.channel.Send("setExtraHTTPHeaders", map[string]interface{}{
+ "headers": serializeMapToNameAndValue(headers),
+ })
+ return err
+}
+
+func (b *browserContextImpl) SetOffline(offline bool) error {
+ _, err := b.channel.Send("setOffline", map[string]interface{}{
+ "offline": offline,
+ })
+ return err
+}
+
+func (b *browserContextImpl) AddInitScript(script Script) error {
+ var source string
+ if script.Content != nil {
+ source = *script.Content
+ }
+ if script.Path != nil {
+ content, err := os.ReadFile(*script.Path)
+ if err != nil {
+ return err
+ }
+ source = string(content)
+ }
+ _, err := b.channel.Send("addInitScript", map[string]interface{}{
+ "source": source,
+ })
+ return err
+}
+
+func (b *browserContextImpl) ExposeBinding(name string, binding BindingCallFunction, handle ...bool) error {
+ needsHandle := false
+ if len(handle) == 1 {
+ needsHandle = handle[0]
+ }
+ for _, page := range b.Pages() {
+ 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.Load(name); ok {
+ return fmt.Errorf("Function '%s' has been already registered", name)
+ }
+ _, err := b.channel.Send("exposeBinding", map[string]interface{}{
+ "name": name,
+ "needsHandle": needsHandle,
+ })
+ if err != nil {
+ return err
+ }
+ b.bindings.Store(name, binding)
+ return err
+}
+
+func (b *browserContextImpl) ExposeFunction(name string, binding ExposedFunction) error {
+ return b.ExposeBinding(name, func(source *BindingSource, args ...interface{}) interface{} {
+ return binding(args...)
+ })
+}
+
+func (b *browserContextImpl) Route(url interface{}, handler routeHandler, times ...int) error {
+ 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()
+ b.routes = remaining
+ if err := b.updateInterceptionPatterns(); err != nil {
+ return err
+ }
+ 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
+}
+
+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 {
+ return b.request
+}
+
+func (b *browserContextImpl) RouteFromHAR(har string, options ...BrowserContextRouteFromHAROptions) error {
+ opt := BrowserContextRouteFromHAROptions{}
+ if len(options) == 1 {
+ opt = options[0]
+ }
+ if opt.Update != nil && *opt.Update {
+ var updateContent *HarContentPolicy
+ switch opt.UpdateContent {
+ case RouteFromHarUpdateContentPolicyAttach:
+ updateContent = HarContentPolicyAttach
+ case RouteFromHarUpdateContentPolicyEmbed:
+ updateContent = HarContentPolicyEmbed
+ }
+ return b.recordIntoHar(har, browserContextRecordIntoHarOptions{
+ URL: opt.URL,
+ UpdateContent: updateContent,
+ UpdateMode: opt.UpdateMode,
+ })
+ }
+ notFound := opt.NotFound
+ if notFound == nil {
+ notFound = HarNotFoundAbort
+ }
+ router := newHarRouter(b.connection.localUtils, har, *notFound, opt.URL)
+ b.harRouters = append(b.harRouters, router)
+ return router.addContextRoute(b)
+}
+
+func (b *browserContextImpl) WaitForEvent(event string, options ...BrowserContextWaitForEventOptions) (interface{}, error) {
+ return b.waiterForEvent(event, options...).Wait()
+}
+
+func (b *browserContextImpl) waiterForEvent(event string, options ...BrowserContextWaitForEventOptions) *waiter {
+ timeout := b.timeoutSettings.Timeout()
+ var predicate interface{} = nil
+ if len(options) == 1 {
+ if options[0].Timeout != nil {
+ timeout = *options[0].Timeout
+ }
+ predicate = options[0].Predicate
+ }
+ waiter := newWaiter().WithTimeout(timeout)
+ waiter.RejectOnEvent(b, "close", ErrTargetClosed)
+ return waiter.WaitForEvent(b, event, predicate)
+}
+
+func (b *browserContextImpl) ExpectConsoleMessage(cb func() error, options ...BrowserContextExpectConsoleMessageOptions) (ConsoleMessage, error) {
+ var w *waiter
+ if len(options) == 1 {
+ w = b.waiterForEvent("console", BrowserContextWaitForEventOptions{
+ Predicate: options[0].Predicate,
+ Timeout: options[0].Timeout,
+ })
+ } else {
+ w = b.waiterForEvent("console")
+ }
+ ret, err := w.RunAndWait(cb)
+ if err != nil {
+ return nil, err
+ }
+ return ret.(ConsoleMessage), nil
+}
+
+func (b *browserContextImpl) ExpectEvent(event string, cb func() error, options ...BrowserContextExpectEventOptions) (interface{}, error) {
+ if len(options) == 1 {
+ return b.waiterForEvent(event, BrowserContextWaitForEventOptions(options[0])).RunAndWait(cb)
+ }
+ return b.waiterForEvent(event).RunAndWait(cb)
+}
+
+func (b *browserContextImpl) ExpectPage(cb func() error, options ...BrowserContextExpectPageOptions) (Page, error) {
+ var w *waiter
+ if len(options) == 1 {
+ w = b.waiterForEvent("page", BrowserContextWaitForEventOptions{
+ Predicate: options[0].Predicate,
+ Timeout: options[0].Timeout,
+ })
+ } else {
+ w = b.waiterForEvent("page")
+ }
+ ret, err := w.RunAndWait(cb)
+ if err != nil {
+ return nil, err
+ }
+ return ret.(Page), nil
+}
+
+func (b *browserContextImpl) Close(options ...BrowserContextCloseOptions) error {
+ if b.closeWasCalled {
+ return nil
+ }
+ 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{}{}
+ if harId != "" {
+ overrides["harId"] = harId
+ }
+ response, err := b.channel.Send("harExport", overrides)
+ if err != nil {
+ return nil, err
+ }
+ artifact := fromChannel(response).(*artifactImpl)
+ // Server side will compress artifact if content is attach or if file is .zip.
+ needCompressed := strings.HasSuffix(strings.ToLower(harMetaData.Path), ".zip")
+ if !needCompressed && harMetaData.Content == HarContentPolicyAttach {
+ tmpPath := harMetaData.Path + ".tmp"
+ if err := artifact.SaveAs(tmpPath); err != nil {
+ return nil, err
+ }
+ err = b.connection.localUtils.HarUnzip(tmpPath, harMetaData.Path)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ if err := artifact.SaveAs(harMetaData.Path); err != nil {
+ return nil, err
+ }
+ }
+ if err := artifact.Delete(); err != nil {
+ return nil, err
+ }
+ }
+ return nil, nil
+ }
+
+ _, err = b.channel.connection.WrapAPICall(innerClose, true)
+ if err != nil {
+ return err
+ }
+
+ _, err = b.channel.Send("close", map[string]interface{}{
+ "reason": b.closeReason,
+ })
+ if err != nil {
+ return err
+ }
+ <-b.closed
+ return err
+}
+
+type browserContextRecordIntoHarOptions struct {
+ Page Page
+ URL interface{}
+ UpdateContent *HarContentPolicy
+ UpdateMode *HarMode
+}
+
+func (b *browserContextImpl) recordIntoHar(har string, options ...browserContextRecordIntoHarOptions) error {
+ overrides := map[string]interface{}{}
+ harOptions := recordHarInputOptions{
+ Path: har,
+ Content: HarContentPolicyAttach,
+ Mode: HarModeMinimal,
+ }
+ if len(options) == 1 {
+ if options[0].UpdateContent != nil {
+ harOptions.Content = options[0].UpdateContent
+ }
+ if options[0].UpdateMode != nil {
+ harOptions.Mode = options[0].UpdateMode
+ }
+ harOptions.URL = options[0].URL
+ overrides["options"] = prepareRecordHarOptions(harOptions)
+ if options[0].Page != nil {
+ overrides["page"] = options[0].Page.(*pageImpl).channel
+ }
+ }
+ harId, err := b.channel.Send("harStart", overrides)
+ if err != nil {
+ return err
+ }
+ b.harRecorders[harId.(string)] = harRecordingMetadata{
+ Path: har,
+ Content: harOptions.Content,
+ }
+ return nil
+}
+
+func (b *browserContextImpl) StorageState(paths ...string) (*StorageState, error) {
+ result, err := b.channel.SendReturnAsDict("storageState")
+ if err != nil {
+ return nil, err
+ }
+ if len(paths) == 1 {
+ file, err := os.Create(paths[0])
+ if err != nil {
+ return nil, err
+ }
+ if err := json.NewEncoder(file).Encode(result); err != nil {
+ return nil, err
+ }
+ if err := file.Close(); err != nil {
+ return nil, err
+ }
+ }
+ var storageState StorageState
+ remapMapToStruct(result, &storageState)
+ return &storageState, nil
+}
+
+func (b *browserContextImpl) onBinding(binding *bindingCallImpl) {
+ function, ok := b.bindings.Load(binding.initializer["name"].(string))
+ if !ok || function == nil {
+ return
+ }
+ go binding.Call(function)
+}
+
+func (b *browserContextImpl) onClose() {
+ if b.browser != nil {
+ contexts := make([]BrowserContext, 0)
+ b.browser.Lock()
+ for _, context := range b.browser.contexts {
+ if context != b {
+ contexts = append(contexts, context)
+ }
+ }
+ b.browser.contexts = contexts
+ b.browser.Unlock()
+ }
+ b.disposeHarRouters()
+ b.Emit("close", b)
+}
+
+func (b *browserContextImpl) onPage(page Page) {
+ b.Lock()
+ b.pages = append(b.pages, page)
+ b.Unlock()
+ b.Emit("page", page)
+ opener, _ := page.Opener()
+ if opener != nil && !opener.IsClosed() {
+ opener.Emit("popup", page)
+ }
+}
+
+func (b *browserContextImpl) onRoute(route *routeImpl) {
+ b.Lock()
+ route.context = b
+ page := route.Request().(*requestImpl).safePage()
+ routes := make([]*routeHandlerEntry, len(b.routes))
+ copy(routes, b.routes)
+ b.Unlock()
+
+ 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 {
+ logger.Error("could not update interception patterns", "error", 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 the page is closed or unrouteAll() was called without waiting and interception disabled,
+ // the method will throw an error - silence it.
+ _ = route.internalContinue(true)
+}
+
+func (b *browserContextImpl) updateInterceptionPatterns() error {
+ patterns := prepareInterceptionPatterns(b.routes)
+ _, err := b.channel.Send("setNetworkInterceptionPatterns", map[string]interface{}{
+ "patterns": patterns,
+ })
+ return err
+}
+
+func (b *browserContextImpl) pause() <-chan error {
+ ret := make(chan error, 1)
+ go func() {
+ _, err := b.channel.Send("pause")
+ ret <- err
+ }()
+ return ret
+}
+
+func (b *browserContextImpl) onBackgroundPage(ev map[string]interface{}) {
+ b.Lock()
+ p := fromChannel(ev["page"]).(*pageImpl)
+ p.browserContext = b
+ b.backgroundPages = append(b.backgroundPages, p)
+ b.Unlock()
+ b.Emit("backgroundpage", p)
+}
+
+func (b *browserContextImpl) onServiceWorker(worker *workerImpl) {
+ worker.context = b
+ b.serviceWorkers = append(b.serviceWorkers, worker)
+ b.Emit("serviceworker", worker)
+}
+
+func (b *browserContextImpl) setOptions(options *BrowserNewContextOptions, tracesDir *string) {
+ if options == nil {
+ options = &BrowserNewContextOptions{}
+ }
+ b.options = options
+ if b.options != nil && b.options.RecordHarPath != nil {
+ b.harRecorders[""] = harRecordingMetadata{
+ Path: *b.options.RecordHarPath,
+ Content: b.options.RecordHarContent,
+ }
+ }
+ if tracesDir != nil {
+ b.tracing.tracesDir = *tracesDir
+ }
+}
+
+func (b *browserContextImpl) BackgroundPages() []Page {
+ b.Lock()
+ defer b.Unlock()
+ return b.backgroundPages
+}
+
+func (b *browserContextImpl) ServiceWorkers() []Worker {
+ b.Lock()
+ defer b.Unlock()
+ 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)
+}
+
+func (b *browserContextImpl) OnConsole(fn func(ConsoleMessage)) {
+ b.On("console", fn)
+}
+
+func (b *browserContextImpl) OnDialog(fn func(Dialog)) {
+ b.On("dialog", fn)
+}
+
+func (b *browserContextImpl) OnPage(fn func(Page)) {
+ b.On("page", fn)
+}
+
+func (b *browserContextImpl) OnRequest(fn func(Request)) {
+ b.On("request", fn)
+}
+
+func (b *browserContextImpl) OnRequestFailed(fn func(Request)) {
+ b.On("requestfailed", fn)
+}
+
+func (b *browserContextImpl) OnRequestFinished(fn func(Request)) {
+ b.On("requestfinished", fn)
+}
+
+func (b *browserContextImpl) OnResponse(fn func(Response)) {
+ b.On("response", fn)
+}
+
+func (b *browserContextImpl) OnWebError(fn func(WebError)) {
+ b.On("weberror", fn)
+}
+
+func (b *browserContextImpl) RouteWebSocket(url interface{}, handler func(WebSocketRoute)) error {
+ b.Lock()
+ defer b.Unlock()
+ b.webSocketRoutes = slices.Insert(b.webSocketRoutes, 0, newWebSocketRouteHandler(newURLMatcher(url, b.options.BaseURL), handler))
+
+ return b.updateWebSocketInterceptionPatterns()
+}
+
+func (b *browserContextImpl) onWebSocketRoute(wr WebSocketRoute) {
+ b.Lock()
+ index := slices.IndexFunc(b.webSocketRoutes, func(r *webSocketRouteHandler) bool {
+ return r.Matches(wr.URL())
+ })
+ if index == -1 {
+ b.Unlock()
+ _, err := wr.ConnectToServer()
+ if err != nil {
+ logger.Error("could not connect to WebSocket server", "error", err)
+ }
+ return
+ }
+ handler := b.webSocketRoutes[index]
+ b.Unlock()
+ handler.Handle(wr)
+}
+
+func (b *browserContextImpl) updateWebSocketInterceptionPatterns() error {
+ patterns := prepareWebSocketRouteHandlerInterceptionPatterns(b.webSocketRoutes)
+ _, err := b.channel.Send("setWebSocketInterceptionPatterns", map[string]interface{}{
+ "patterns": patterns,
+ })
+ return err
+}
+
+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: 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" {
+ bt.browser = fromChannel(parent.channel).(*browserImpl)
+ bt.browser.contexts = append(bt.browser.contexts, bt)
+ }
+ 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))
+ })
+
+ bt.channel.On("close", bt.onClose)
+ bt.channel.On("page", func(payload map[string]interface{}) {
+ bt.onPage(fromChannel(payload["page"]).(*pageImpl))
+ })
+ bt.channel.On("route", func(params map[string]interface{}) {
+ bt.channel.CreateTask(func() {
+ bt.onRoute(fromChannel(params["route"]).(*routeImpl))
+ })
+ })
+ bt.channel.On("webSocketRoute", func(params map[string]interface{}) {
+ bt.channel.CreateTask(func() {
+ bt.onWebSocketRoute(fromChannel(params["webSocketRoute"]).(*webSocketRouteImpl))
+ })
+ })
+ bt.channel.On("backgroundPage", bt.onBackgroundPage)
+ bt.channel.On("serviceWorker", func(params map[string]interface{}) {
+ bt.onServiceWorker(fromChannel(params["worker"]).(*workerImpl))
+ })
+ bt.channel.On("console", func(ev map[string]interface{}) {
+ message := newConsoleMessage(ev)
+ bt.Emit("console", message)
+ if message.page != nil {
+ message.page.Emit("console", message)
+ }
+ })
+ bt.channel.On("dialog", func(params map[string]interface{}) {
+ dialog := fromChannel(params["dialog"]).(*dialogImpl)
+ go func() {
+ hasListeners := bt.Emit("dialog", dialog)
+ page := dialog.page
+ if page != nil {
+ if page.Emit("dialog", dialog) {
+ hasListeners = true
+ }
+ }
+ if !hasListeners {
+ // Although we do similar handling on the server side, we still need this logic
+ // on the client side due to a possible race condition between two async calls:
+ // a) removing "dialog" listener subscription (client->server)
+ // b) actual "dialog" event (server->client)
+ if dialog.Type() == "beforeunload" {
+ _ = dialog.Accept()
+ } else {
+ _ = dialog.Dismiss()
+ }
+ }
+ }()
+ })
+ bt.channel.On(
+ "pageError", func(ev map[string]interface{}) {
+ 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))
+ page.(*pageImpl).Emit("pageerror", err)
+ } else {
+ bt.Emit("weberror", newWebError(nil, err))
+ }
+ },
+ )
+ bt.channel.On("request", func(ev map[string]interface{}) {
+ request := fromChannel(ev["request"]).(*requestImpl)
+ page := fromNullableChannel(ev["page"])
+ bt.Emit("request", request)
+ if page != nil {
+ page.(*pageImpl).Emit("request", request)
+ }
+ })
+ bt.channel.On("requestFailed", func(ev map[string]interface{}) {
+ request := fromChannel(ev["request"]).(*requestImpl)
+ failureText := ev["failureText"]
+ if failureText != nil {
+ request.failureText = failureText.(string)
+ }
+ page := fromNullableChannel(ev["page"])
+ request.setResponseEndTiming(ev["responseEndTiming"].(float64))
+ bt.Emit("requestfailed", request)
+ if page != nil {
+ page.(*pageImpl).Emit("requestfailed", request)
+ }
+ })
+
+ bt.channel.On("requestFinished", func(ev map[string]interface{}) {
+ request := fromChannel(ev["request"]).(*requestImpl)
+ response := fromNullableChannel(ev["response"])
+ page := fromNullableChannel(ev["page"])
+ request.setResponseEndTiming(ev["responseEndTiming"].(float64))
+ bt.Emit("requestfinished", request)
+ if page != nil {
+ page.(*pageImpl).Emit("requestfinished", request)
+ }
+ if response != nil {
+ close(response.(*responseImpl).finished)
+ }
+ })
+ bt.channel.On("response", func(ev map[string]interface{}) {
+ response := fromChannel(ev["response"]).(*responseImpl)
+ page := fromNullableChannel(ev["page"])
+ bt.Emit("response", response)
+ if page != nil {
+ page.(*pageImpl).Emit("response", response)
+ }
+ })
+ bt.Once("close", func() {
+ bt.closed <- struct{}{}
+ })
+ bt.setEventSubscriptionMapping(map[string]string{
+ "console": "console",
+ "dialog": "dialog",
+ "request": "request",
+ "response": "response",
+ "requestfinished": "requestFinished",
+ "responsefailed": "responseFailed",
+ })
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/browser_type.go b/vendor/github.com/playwright-community/playwright-go/browser_type.go
new file mode 100644
index 0000000..41a8b18
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/browser_type.go
@@ -0,0 +1,181 @@
+package playwright
+
+import (
+ "fmt"
+)
+
+type browserTypeImpl struct {
+ channelOwner
+ playwright *Playwright
+}
+
+func (b *browserTypeImpl) Name() string {
+ return b.initializer["name"].(string)
+}
+
+func (b *browserTypeImpl) ExecutablePath() string {
+ return b.initializer["executablePath"].(string)
+}
+
+func (b *browserTypeImpl) Launch(options ...BrowserTypeLaunchOptions) (Browser, error) {
+ overrides := map[string]interface{}{}
+ if len(options) == 1 && options[0].Env != nil {
+ overrides["env"] = serializeMapToNameAndValue(options[0].Env)
+ options[0].Env = nil
+ }
+ channel, err := b.channel.Send("launch", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ browser := fromChannel(channel).(*browserImpl)
+ b.didLaunchBrowser(browser)
+ return browser, nil
+}
+
+func (b *browserTypeImpl) LaunchPersistentContext(userDataDir string, options ...BrowserTypeLaunchPersistentContextOptions) (BrowserContext, error) {
+ overrides := map[string]interface{}{
+ "userDataDir": userDataDir,
+ }
+ option := &BrowserNewContextOptions{}
+ var tracesDir *string = nil
+ if len(options) == 1 {
+ tracesDir = options[0].TracesDir
+ err := assignStructFields(option, options[0], true)
+ if err != nil {
+ return nil, fmt.Errorf("can not convert options: %w", err)
+ }
+ if options[0].AcceptDownloads != nil {
+ if *options[0].AcceptDownloads {
+ overrides["acceptDownloads"] = "accept"
+ } else {
+ overrides["acceptDownloads"] = "deny"
+ }
+ 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
+ }
+ if options[0].Env != nil {
+ overrides["env"] = serializeMapToNameAndValue(options[0].Env)
+ options[0].Env = nil
+ }
+ if options[0].NoViewport != nil && *options[0].NoViewport {
+ overrides["noDefaultViewport"] = true
+ options[0].NoViewport = nil
+ }
+ if options[0].RecordHarPath != nil {
+ overrides["recordHar"] = prepareRecordHarOptions(recordHarInputOptions{
+ Path: *options[0].RecordHarPath,
+ URL: options[0].RecordHarURLFilter,
+ Mode: options[0].RecordHarMode,
+ Content: options[0].RecordHarContent,
+ OmitContent: options[0].RecordHarOmitContent,
+ })
+ options[0].RecordHarPath = nil
+ options[0].RecordHarURLFilter = nil
+ options[0].RecordHarMode = nil
+ options[0].RecordHarContent = nil
+ options[0].RecordHarOmitContent = nil
+ }
+ }
+ channel, err := b.channel.Send("launchPersistentContext", options, overrides)
+ if err != nil {
+ 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,
+ "headers": map[string]string{
+ "x-playwright-browser": b.Name(),
+ },
+ }
+ if len(options) == 1 {
+ if options[0].Headers != nil {
+ for k, v := range options[0].Headers {
+ overrides["headers"].(map[string]string)[k] = v
+ }
+ options[0].Headers = nil
+ }
+ }
+ localUtils := b.connection.LocalUtils()
+ pipe, err := localUtils.channel.SendReturnAsDict("connect", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ jsonPipe := fromChannel(pipe["pipe"]).(*jsonPipe)
+ 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()
+ for _, page := range pages {
+ page.(*pageImpl).onClose()
+ }
+ context.(*browserContextImpl).onClose()
+ }
+ browser.onClose()
+ connection.cleanup()
+ }
+ jsonPipe.On("closed", pipeClosed)
+
+ b.didLaunchBrowser(browser)
+ return browser, nil
+}
+
+func (b *browserTypeImpl) ConnectOverCDP(endpointURL string, options ...BrowserTypeConnectOverCDPOptions) (Browser, error) {
+ overrides := map[string]interface{}{
+ "endpointURL": endpointURL,
+ }
+ if len(options) == 1 {
+ if options[0].Headers != nil {
+ overrides["headers"] = serializeMapToNameAndValue(options[0].Headers)
+ options[0].Headers = nil
+ }
+ }
+ response, err := b.channel.SendReturnAsDict("connectOverCDP", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ browser := fromChannel(response["browser"]).(*browserImpl)
+ b.didLaunchBrowser(browser)
+ if defaultContext, ok := response["defaultContext"]; ok {
+ context := fromChannel(defaultContext).(*browserContextImpl)
+ b.didCreateContext(context, nil, nil)
+ }
+ return browser, nil
+}
+
+func (b *browserTypeImpl) didCreateContext(context *browserContextImpl, contextOptions *BrowserNewContextOptions, tracesDir *string) {
+ context.setOptions(contextOptions, tracesDir)
+}
+
+func (b *browserTypeImpl) didLaunchBrowser(browser *browserImpl) {
+ browser.browserType = b
+}
+
+func newBrowserType(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *browserTypeImpl {
+ bt := &browserTypeImpl{}
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/cdp_session.go b/vendor/github.com/playwright-community/playwright-go/cdp_session.go
new file mode 100644
index 0000000..e9bba82
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/cdp_session.go
@@ -0,0 +1,38 @@
+package playwright
+
+type cdpSessionImpl struct {
+ channelOwner
+}
+
+func (c *cdpSessionImpl) Detach() error {
+ _, err := c.channel.Send("detach")
+ return err
+}
+
+func (c *cdpSessionImpl) Send(method string, params map[string]interface{}) (interface{}, error) {
+ result, err := c.channel.Send("send", map[string]interface{}{
+ "method": method,
+ "params": params,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ return result, err
+}
+
+func (c *cdpSessionImpl) onEvent(params map[string]interface{}) {
+ c.Emit(params["method"].(string), params["params"])
+}
+
+func newCDPSession(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *cdpSessionImpl {
+ bt := &cdpSessionImpl{}
+
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+
+ bt.channel.On("event", func(params map[string]interface{}) {
+ bt.onEvent(params)
+ })
+
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/channel.go b/vendor/github.com/playwright-community/playwright-go/channel.go
new file mode 100644
index 0000000..b0bded4
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/channel.go
@@ -0,0 +1,92 @@
+package playwright
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+type channel struct {
+ eventEmitter
+ guid string
+ connection *connection
+ owner *channelOwner // to avoid type conversion
+ object interface{} // retain type info (for fromChannel needed)
+}
+
+func (c *channel) MarshalJSON() ([]byte, error) {
+ return json.Marshal(map[string]string{
+ "guid": c.guid,
+ })
+}
+
+// for catch errors of route handlers etc.
+func (c *channel) CreateTask(fn func()) {
+ go func() {
+ defer func() {
+ if e := recover(); e != nil {
+ err, ok := e.(error)
+ if ok {
+ c.connection.err.Set(err)
+ } else {
+ c.connection.err.Set(fmt.Errorf("%v", e))
+ }
+ }
+ }()
+ fn()
+ }()
+}
+
+func (c *channel) Send(method string, options ...interface{}) (interface{}, error) {
+ return c.connection.WrapAPICall(func() (interface{}, error) {
+ return c.innerSend(method, options...).GetResultValue()
+ }, c.owner.isInternalType)
+}
+
+func (c *channel) SendReturnAsDict(method string, options ...interface{}) (map[string]interface{}, error) {
+ ret, err := c.connection.WrapAPICall(func() (interface{}, error) {
+ return c.innerSend(method, options...).GetResult()
+ }, c.owner.isInternalType)
+ return ret.(map[string]interface{}), err
+}
+
+func (c *channel) innerSend(method string, options ...interface{}) *protocolCallback {
+ if err := c.connection.err.Get(); err != nil {
+ c.connection.err.Set(nil)
+ pc := newProtocolCallback(false, c.connection.abort)
+ pc.SetError(err)
+ return pc
+ }
+ params := transformOptions(options...)
+ return c.connection.sendMessageToServer(c.owner, method, params, false)
+}
+
+// SendNoReply ignores return value and errors
+// almost equivalent to `send(...).catch(() => {})`
+func (c *channel) SendNoReply(method string, options ...interface{}) {
+ c.innerSendNoReply(method, c.owner.isInternalType, options...)
+}
+
+func (c *channel) SendNoReplyInternal(method string, options ...interface{}) {
+ c.innerSendNoReply(method, true, options...)
+}
+
+func (c *channel) innerSendNoReply(method string, isInternal bool, options ...interface{}) {
+ params := transformOptions(options...)
+ _, err := c.connection.WrapAPICall(func() (interface{}, error) {
+ return c.connection.sendMessageToServer(c.owner, method, params, true).GetResult()
+ }, isInternal)
+ if err != nil {
+ // ignore error actively, log only for debug
+ logger.Error("SendNoReply failed", "error", err)
+ }
+}
+
+func newChannel(owner *channelOwner, object interface{}) *channel {
+ channel := &channel{
+ connection: owner.connection,
+ guid: owner.guid,
+ owner: owner,
+ object: object,
+ }
+ 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
new file mode 100644
index 0000000..5159eb2
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/channel_owner.go
@@ -0,0 +1,122 @@
+package playwright
+
+import (
+ "sync"
+)
+
+type channelOwner struct {
+ sync.RWMutex
+ eventEmitter
+ objectType string
+ guid string
+ channel *channel
+ objects map[string]*channelOwner
+ eventToSubscriptionMapping map[string]string
+ connection *connection
+ initializer map[string]interface{}
+ parent *channelOwner
+ wasCollected bool
+ isInternalType bool
+}
+
+func (c *channelOwner) dispose(reason ...string) {
+ // Clean up from parent and connection.
+ if c.parent != nil {
+ delete(c.parent.objects, c.guid)
+ }
+ c.connection.objects.Delete(c.guid)
+ if len(reason) > 0 {
+ c.wasCollected = reason[0] == "gc"
+ }
+
+ // Dispose all children.
+ for _, object := range c.objects {
+ object.dispose(reason...)
+ }
+ c.objects = make(map[string]*channelOwner)
+}
+
+func (c *channelOwner) adopt(child *channelOwner) {
+ delete(child.parent.objects, child.guid)
+ c.objects[child.guid] = child
+ child.parent = c
+}
+
+func (c *channelOwner) setEventSubscriptionMapping(mapping map[string]string) {
+ c.eventToSubscriptionMapping = mapping
+}
+
+func (c *channelOwner) updateSubscription(event string, enabled bool) {
+ protocolEvent, ok := c.eventToSubscriptionMapping[event]
+ if ok {
+ c.channel.SendNoReplyInternal("updateSubscription", map[string]interface{}{
+ "event": protocolEvent,
+ "enabled": enabled,
+ })
+ }
+}
+
+func (c *channelOwner) Once(name string, handler interface{}) {
+ c.addEvent(name, handler, true)
+}
+
+func (c *channelOwner) On(name string, handler interface{}) {
+ c.addEvent(name, handler, false)
+}
+
+func (c *channelOwner) addEvent(name string, handler interface{}, once bool) {
+ if c.ListenerCount(name) == 0 {
+ c.updateSubscription(name, true)
+ }
+ c.eventEmitter.addEvent(name, handler, once)
+}
+
+func (c *channelOwner) RemoveListener(name string, handler interface{}) {
+ c.eventEmitter.RemoveListener(name, handler)
+ if c.ListenerCount(name) == 0 {
+ c.updateSubscription(name, false)
+ }
+}
+
+func (c *channelOwner) createChannelOwner(self interface{}, parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) {
+ c.objectType = objectType
+ c.guid = guid
+ c.wasCollected = false
+ c.parent = parent
+ c.objects = make(map[string]*channelOwner)
+ c.initializer = initializer
+ if c.parent != nil {
+ c.connection = parent.connection
+ c.parent.objects[guid] = c
+ }
+ if c.connection != nil {
+ c.connection.objects.Store(guid, c)
+ }
+ c.channel = newChannel(c, self)
+ c.eventToSubscriptionMapping = map[string]string{}
+}
+
+func (c *channelOwner) markAsInternalType() {
+ c.isInternalType = true
+}
+
+type rootChannelOwner struct {
+ channelOwner
+}
+
+func (r *rootChannelOwner) initialize() (*Playwright, error) {
+ ret, err := r.channel.SendReturnAsDict("initialize", map[string]interface{}{
+ "sdkLanguage": "javascript",
+ })
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(ret["playwright"]).(*Playwright), nil
+}
+
+func newRootChannelOwner(connection *connection) *rootChannelOwner {
+ c := &rootChannelOwner{}
+ c.connection = connection
+ c.createChannelOwner(c, nil, "Root", "", make(map[string]interface{}))
+ return c
+}
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 0000000..8bab037
--- /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/cmd/playwright/main.go b/vendor/github.com/playwright-community/playwright-go/cmd/playwright/main.go
new file mode 100644
index 0000000..95e7d85
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/cmd/playwright/main.go
@@ -0,0 +1,25 @@
+package main
+
+import (
+ "log"
+ "os"
+
+ "github.com/playwright-community/playwright-go"
+)
+
+func main() {
+ driver, err := playwright.NewDriver(&playwright.RunOptions{})
+ if err != nil {
+ log.Fatalf("could not start driver: %v", err)
+ }
+ if err = driver.DownloadDriver(); err != nil {
+ log.Fatalf("could not download driver: %v", err)
+ }
+ cmd := driver.Command(os.Args[1:]...)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ log.Fatalf("could not run driver: %v", err)
+ }
+ os.Exit(cmd.ProcessState.ExitCode())
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/connection.go b/vendor/github.com/playwright-community/playwright-go/connection.go
new file mode 100644
index 0000000..ba1e365
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/connection.go
@@ -0,0 +1,401 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "regexp"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/go-stack/stack"
+ "github.com/playwright-community/playwright-go/internal/safe"
+)
+
+var (
+ pkgSourcePathPattern = regexp.MustCompile(`.+[\\/]playwright-go[\\/][^\\/]+\.go`)
+ apiNameTransform = regexp.MustCompile(`(?U)\(\*(.+)(Impl)?\)`)
+)
+
+type connection struct {
+ transport transport
+ apiZone sync.Map
+ objects *safe.SyncMap[string, *channelOwner]
+ lastID atomic.Uint32
+ rootObject *rootChannelOwner
+ callbacks *safe.SyncMap[uint32, *protocolCallback]
+ afterClose func()
+ onClose func() error
+ isRemote bool
+ localUtils *localUtilsImpl
+ tracingCount atomic.Int32
+ abort chan struct{}
+ abortOnce sync.Once
+ err *safeValue[error] // for event listener error
+ closedError *safeValue[error]
+}
+
+func (c *connection) Start() (*Playwright, error) {
+ go func() {
+ for {
+ msg, err := c.transport.Poll()
+ if err != nil {
+ _ = c.transport.Close()
+ c.cleanup(err)
+ return
+ }
+ c.Dispatch(msg)
+ }
+ }()
+
+ c.onClose = func() error {
+ if err := c.transport.Close(); err != nil {
+ return err
+ }
+ return nil
+ }
+
+ return c.rootObject.initialize()
+}
+
+func (c *connection) Stop() error {
+ if err := c.onClose(); err != nil {
+ return err
+ }
+ c.cleanup()
+ return nil
+}
+
+func (c *connection) cleanup(cause ...error) {
+ if len(cause) > 0 {
+ c.closedError.Set(fmt.Errorf("%w: %w", ErrTargetClosed, cause[0]))
+ } else {
+ c.closedError.Set(ErrTargetClosed)
+ }
+ if c.afterClose != nil {
+ c.afterClose()
+ }
+ c.abortOnce.Do(func() {
+ select {
+ case <-c.abort:
+ default:
+ close(c.abort)
+ }
+ })
+}
+
+func (c *connection) Dispatch(msg *message) {
+ if c.closedError.Get() != nil {
+ return
+ }
+ method := msg.Method
+ if msg.ID != 0 {
+ cb, _ := c.callbacks.LoadAndDelete(uint32(msg.ID))
+ if cb.noReply {
+ return
+ }
+ if msg.Error != nil {
+ cb.SetError(parseError(msg.Error.Error))
+ } else {
+ cb.SetResult(c.replaceGuidsWithChannels(msg.Result).(map[string]interface{}))
+ }
+ return
+ }
+ object, _ := c.objects.Load(msg.GUID)
+ if method == "__create__" {
+ c.createRemoteObject(
+ object, msg.Params["type"].(string), msg.Params["guid"].(string), msg.Params["initializer"],
+ )
+ return
+ }
+ if object == nil {
+ return
+ }
+ if method == "__adopt__" {
+ child, ok := c.objects.Load(msg.Params["guid"].(string))
+ if !ok {
+ return
+ }
+ object.adopt(child)
+ return
+ }
+ if method == "__dispose__" {
+ reason, ok := msg.Params["reason"]
+ if ok {
+ object.dispose(reason.(string))
+ } else {
+ object.dispose()
+ }
+ return
+ }
+ if object.objectType == "JsonPipe" {
+ object.channel.Emit(method, msg.Params)
+ } else {
+ object.channel.Emit(method, c.replaceGuidsWithChannels(msg.Params))
+ }
+}
+
+func (c *connection) LocalUtils() *localUtilsImpl {
+ return c.localUtils
+}
+
+func (c *connection) createRemoteObject(parent *channelOwner, objectType string, guid string, initializer interface{}) interface{} {
+ initializer = c.replaceGuidsWithChannels(initializer)
+ result := createObjectFactory(parent, objectType, guid, initializer.(map[string]interface{}))
+ return result
+}
+
+func (c *connection) WrapAPICall(cb func() (interface{}, error), isInternal bool) (interface{}, error) {
+ if _, ok := c.apiZone.Load("apiZone"); ok {
+ return cb()
+ }
+ c.apiZone.Store("apiZone", serializeCallStack(isInternal))
+ return cb()
+}
+
+func (c *connection) replaceGuidsWithChannels(payload interface{}) interface{} {
+ if payload == nil {
+ return nil
+ }
+ v := reflect.ValueOf(payload)
+ if v.Kind() == reflect.Slice {
+ listV := payload.([]interface{})
+ for i := 0; i < len(listV); i++ {
+ listV[i] = c.replaceGuidsWithChannels(listV[i])
+ }
+ return listV
+ }
+ if v.Kind() == reflect.Map {
+ mapV := payload.(map[string]interface{})
+ if guid, hasGUID := mapV["guid"]; hasGUID {
+ if channelOwner, ok := c.objects.Load(guid.(string)); ok {
+ return channelOwner.channel
+ }
+ }
+ for key := range mapV {
+ mapV[key] = c.replaceGuidsWithChannels(mapV[key])
+ }
+ return mapV
+ }
+ return payload
+}
+
+func (c *connection) sendMessageToServer(object *channelOwner, method string, params interface{}, noReply bool) (cb *protocolCallback) {
+ cb = newProtocolCallback(noReply, c.abort)
+
+ if err := c.closedError.Get(); err != nil {
+ cb.SetError(err)
+ return
+ }
+ if object.wasCollected {
+ cb.SetError(errors.New("The object has been collected to prevent unbounded heap growth."))
+ return
+ }
+
+ id := c.lastID.Add(1)
+ c.callbacks.Store(id, cb)
+ var (
+ metadata = make(map[string]interface{}, 0)
+ stack = make([]map[string]interface{}, 0)
+ )
+ apiZone, ok := c.apiZone.LoadAndDelete("apiZone")
+ if ok {
+ for k, v := range apiZone.(parsedStackTrace).metadata {
+ metadata[k] = v
+ }
+ stack = append(stack, apiZone.(parsedStackTrace).frames...)
+ }
+ metadata["wallTime"] = time.Now().UnixMilli()
+ message := map[string]interface{}{
+ "id": id,
+ "guid": object.guid,
+ "method": method,
+ "params": params, // channel.MarshalJSON will replace channel with guid
+ "metadata": metadata,
+ }
+ if c.tracingCount.Load() > 0 && len(stack) > 0 && object.guid != "localUtils" {
+ c.LocalUtils().AddStackToTracingNoReply(id, stack)
+ }
+
+ if err := c.transport.Send(message); err != nil {
+ cb.SetError(fmt.Errorf("could not send message: %w", err))
+ return
+ }
+
+ return
+}
+
+func (c *connection) setInTracing(isTracing bool) {
+ if isTracing {
+ c.tracingCount.Add(1)
+ } else {
+ c.tracingCount.Add(-1)
+ }
+}
+
+type parsedStackTrace struct {
+ frames []map[string]interface{}
+ metadata map[string]interface{}
+}
+
+func serializeCallStack(isInternal bool) parsedStackTrace {
+ st := stack.Trace().TrimRuntime()
+ if len(st) == 0 { // https://github.com/go-stack/stack/issues/27
+ st = stack.Trace()
+ }
+
+ lastInternalIndex := 0
+ for i, s := range st {
+ if pkgSourcePathPattern.MatchString(s.Frame().File) {
+ lastInternalIndex = i
+ }
+ }
+ apiName := ""
+ if !isInternal {
+ apiName = fmt.Sprintf("%n", st[lastInternalIndex])
+ }
+ st = st.TrimBelow(st[lastInternalIndex])
+
+ callStack := make([]map[string]interface{}, 0)
+ for i, s := range st {
+ if i == 0 {
+ continue
+ }
+ callStack = append(callStack, map[string]interface{}{
+ "file": s.Frame().File,
+ "line": s.Frame().Line,
+ "column": 0,
+ "function": s.Frame().Function,
+ })
+ }
+ metadata := make(map[string]interface{})
+ if len(st) > 1 {
+ metadata["location"] = serializeCallLocation(st[1])
+ }
+ apiName = apiNameTransform.ReplaceAllString(apiName, "$1")
+ if len(apiName) > 1 {
+ apiName = strings.ToUpper(apiName[:1]) + apiName[1:]
+ }
+ metadata["apiName"] = apiName
+ metadata["isInternal"] = isInternal
+ return parsedStackTrace{
+ metadata: metadata,
+ frames: callStack,
+ }
+}
+
+func serializeCallLocation(caller stack.Call) map[string]interface{} {
+ line, _ := strconv.Atoi(fmt.Sprintf("%d", caller))
+ return map[string]interface{}{
+ "file": fmt.Sprintf("%s", caller),
+ "line": line,
+ }
+}
+
+func newConnection(transport transport, localUtils ...*localUtilsImpl) *connection {
+ connection := &connection{
+ abort: make(chan struct{}, 1),
+ callbacks: safe.NewSyncMap[uint32, *protocolCallback](),
+ objects: safe.NewSyncMap[string, *channelOwner](),
+ transport: transport,
+ isRemote: false,
+ err: &safeValue[error]{},
+ closedError: &safeValue[error]{},
+ }
+ if len(localUtils) > 0 {
+ connection.localUtils = localUtils[0]
+ connection.isRemote = true
+ }
+ connection.rootObject = newRootChannelOwner(connection)
+ return connection
+}
+
+func fromChannel(v interface{}) interface{} {
+ return v.(*channel).object
+}
+
+func fromNullableChannel(v interface{}) interface{} {
+ if v == nil {
+ return nil
+ }
+ return fromChannel(v)
+}
+
+type protocolCallback struct {
+ done chan struct{}
+ noReply bool
+ abort <-chan struct{}
+ once sync.Once
+ value map[string]interface{}
+ err error
+}
+
+func (pc *protocolCallback) setResultOnce(result map[string]interface{}, err error) {
+ pc.once.Do(func() {
+ pc.value = result
+ pc.err = err
+ close(pc.done)
+ })
+}
+
+func (pc *protocolCallback) waitResult() {
+ if pc.noReply {
+ return
+ }
+ select {
+ case <-pc.done: // wait for result
+ return
+ case <-pc.abort:
+ select {
+ case <-pc.done:
+ return
+ default:
+ pc.err = errors.New("Connection closed")
+ return
+ }
+ }
+}
+
+func (pc *protocolCallback) SetError(err error) {
+ pc.setResultOnce(nil, err)
+}
+
+func (pc *protocolCallback) SetResult(result map[string]interface{}) {
+ pc.setResultOnce(result, nil)
+}
+
+func (pc *protocolCallback) GetResult() (map[string]interface{}, error) {
+ pc.waitResult()
+ return pc.value, pc.err
+}
+
+// GetResultValue returns value if the map has only one element
+func (pc *protocolCallback) GetResultValue() (interface{}, error) {
+ pc.waitResult()
+ if len(pc.value) == 0 { // empty map treated as nil
+ return nil, pc.err
+ }
+ if len(pc.value) == 1 {
+ for key := range pc.value {
+ return pc.value[key], pc.err
+ }
+ }
+
+ return pc.value, pc.err
+}
+
+func newProtocolCallback(noReply bool, abort <-chan struct{}) *protocolCallback {
+ if noReply {
+ return &protocolCallback{
+ noReply: true,
+ abort: abort,
+ }
+ }
+ return &protocolCallback{
+ done: make(chan struct{}, 1),
+ abort: abort,
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/console_message.go b/vendor/github.com/playwright-community/playwright-go/console_message.go
new file mode 100644
index 0000000..4baf3f1
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/console_message.go
@@ -0,0 +1,47 @@
+package playwright
+
+type consoleMessageImpl struct {
+ event map[string]interface{}
+ page Page
+}
+
+func (c *consoleMessageImpl) Type() string {
+ return c.event["type"].(string)
+}
+
+func (c *consoleMessageImpl) Text() string {
+ return c.event["text"].(string)
+}
+
+func (c *consoleMessageImpl) String() string {
+ return c.Text()
+}
+
+func (c *consoleMessageImpl) Args() []JSHandle {
+ args := c.event["args"].([]interface{})
+ out := []JSHandle{}
+ for idx := range args {
+ out = append(out, fromChannel(args[idx]).(*jsHandleImpl))
+ }
+ return out
+}
+
+func (c *consoleMessageImpl) Location() *ConsoleMessageLocation {
+ location := &ConsoleMessageLocation{}
+ remapMapToStruct(c.event["location"], location)
+ return location
+}
+
+func (c *consoleMessageImpl) Page() Page {
+ return c.page
+}
+
+func newConsoleMessage(event map[string]interface{}) *consoleMessageImpl {
+ bt := &consoleMessageImpl{}
+ bt.event = event
+ page := fromNullableChannel(event["page"])
+ if page != nil {
+ bt.page = page.(*pageImpl)
+ }
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/dialog.go b/vendor/github.com/playwright-community/playwright-go/dialog.go
new file mode 100644
index 0000000..8d13234
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/dialog.go
@@ -0,0 +1,48 @@
+package playwright
+
+type dialogImpl struct {
+ channelOwner
+ page Page
+}
+
+func (d *dialogImpl) Type() string {
+ return d.initializer["type"].(string)
+}
+
+func (d *dialogImpl) Message() string {
+ return d.initializer["message"].(string)
+}
+
+func (d *dialogImpl) DefaultValue() string {
+ return d.initializer["defaultValue"].(string)
+}
+
+func (d *dialogImpl) Accept(promptTextInput ...string) error {
+ var promptText *string
+ if len(promptTextInput) == 1 {
+ promptText = &promptTextInput[0]
+ }
+ _, err := d.channel.Send("accept", map[string]interface{}{
+ "promptText": promptText,
+ })
+ return err
+}
+
+func (d *dialogImpl) Dismiss() error {
+ _, err := d.channel.Send("dismiss")
+ return err
+}
+
+func (d *dialogImpl) Page() Page {
+ return d.page
+}
+
+func newDialog(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *dialogImpl {
+ bt := &dialogImpl{}
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ page := fromNullableChannel(initializer["page"])
+ if page != nil {
+ bt.page = page.(*pageImpl)
+ }
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/download.go b/vendor/github.com/playwright-community/playwright-go/download.go
new file mode 100644
index 0000000..b9d2024
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/download.go
@@ -0,0 +1,56 @@
+package playwright
+
+type downloadImpl struct {
+ page *pageImpl
+ url string
+ suggestedFilename string
+ artifact *artifactImpl
+}
+
+func (d *downloadImpl) String() string {
+ return d.SuggestedFilename()
+}
+
+func (d *downloadImpl) Page() Page {
+ return d.page
+}
+
+func (d *downloadImpl) URL() string {
+ return d.url
+}
+
+func (d *downloadImpl) SuggestedFilename() string {
+ return d.suggestedFilename
+}
+
+func (d *downloadImpl) Delete() error {
+ err := d.artifact.Delete()
+ return err
+}
+
+func (d *downloadImpl) Failure() error {
+ return d.artifact.Failure()
+}
+
+func (d *downloadImpl) Path() (string, error) {
+ path, err := d.artifact.PathAfterFinished()
+ return path, err
+}
+
+func (d *downloadImpl) SaveAs(path string) error {
+ err := d.artifact.SaveAs(path)
+ return err
+}
+
+func (d *downloadImpl) Cancel() error {
+ return d.artifact.Cancel()
+}
+
+func newDownload(page *pageImpl, url string, suggestedFilename string, artifact *artifactImpl) *downloadImpl {
+ return &downloadImpl{
+ page: page,
+ url: url,
+ suggestedFilename: suggestedFilename,
+ artifact: artifact,
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/element_handle.go b/vendor/github.com/playwright-community/playwright-go/element_handle.go
new file mode 100644
index 0000000..62c41ba
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/element_handle.go
@@ -0,0 +1,403 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "os"
+)
+
+type elementHandleImpl struct {
+ jsHandleImpl
+}
+
+func (e *elementHandleImpl) AsElement() ElementHandle {
+ return e
+}
+
+func (e *elementHandleImpl) OwnerFrame() (Frame, error) {
+ channel, err := e.channel.Send("ownerFrame")
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ return nil, nil
+ }
+ return channelOwner.(*frameImpl), nil
+}
+
+func (e *elementHandleImpl) ContentFrame() (Frame, error) {
+ channel, err := e.channel.Send("contentFrame")
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ return nil, nil
+ }
+ return channelOwner.(*frameImpl), nil
+}
+
+func (e *elementHandleImpl) GetAttribute(name string) (string, error) {
+ attribute, err := e.channel.Send("getAttribute", map[string]interface{}{
+ "name": name,
+ })
+ if attribute == nil {
+ return "", err
+ }
+ return attribute.(string), err
+}
+
+func (e *elementHandleImpl) TextContent() (string, error) {
+ textContent, err := e.channel.Send("textContent")
+ if textContent == nil {
+ return "", err
+ }
+ return textContent.(string), err
+}
+
+func (e *elementHandleImpl) InnerText() (string, error) {
+ innerText, err := e.channel.Send("innerText")
+ if innerText == nil {
+ return "", err
+ }
+ return innerText.(string), err
+}
+
+func (e *elementHandleImpl) InnerHTML() (string, error) {
+ innerHTML, err := e.channel.Send("innerHTML")
+ if innerHTML == nil {
+ return "", err
+ }
+ return innerHTML.(string), err
+}
+
+func (e *elementHandleImpl) DispatchEvent(typ string, initObjects ...interface{}) error {
+ var initObject interface{}
+ if len(initObjects) == 1 {
+ initObject = initObjects[0]
+ }
+ _, err := e.channel.Send("dispatchEvent", map[string]interface{}{
+ "type": typ,
+ "eventInit": serializeArgument(initObject),
+ })
+ return err
+}
+
+func (e *elementHandleImpl) Hover(options ...ElementHandleHoverOptions) error {
+ _, err := e.channel.Send("hover", options)
+ return err
+}
+
+func (e *elementHandleImpl) Click(options ...ElementHandleClickOptions) error {
+ _, err := e.channel.Send("click", options)
+ return err
+}
+
+func (e *elementHandleImpl) Dblclick(options ...ElementHandleDblclickOptions) error {
+ _, err := e.channel.Send("dblclick", options)
+ return err
+}
+
+func (e *elementHandleImpl) QuerySelector(selector string) (ElementHandle, error) {
+ channel, err := e.channel.Send("querySelector", map[string]interface{}{
+ "selector": selector,
+ })
+ if err != nil {
+ return nil, err
+ }
+ if channel == nil {
+ return nil, nil
+ }
+ return fromChannel(channel).(*elementHandleImpl), nil
+}
+
+func (e *elementHandleImpl) QuerySelectorAll(selector string) ([]ElementHandle, error) {
+ channels, err := e.channel.Send("querySelectorAll", map[string]interface{}{
+ "selector": selector,
+ })
+ if err != nil {
+ return nil, err
+ }
+ elements := make([]ElementHandle, 0)
+ for _, channel := range channels.([]interface{}) {
+ elements = append(elements, fromChannel(channel).(*elementHandleImpl))
+ }
+ return elements, nil
+}
+
+func (e *elementHandleImpl) EvalOnSelector(selector string, expression string, options ...interface{}) (interface{}, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := e.channel.Send("evalOnSelector", map[string]interface{}{
+ "selector": selector,
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(result), nil
+}
+
+func (e *elementHandleImpl) EvalOnSelectorAll(selector string, expression string, options ...interface{}) (interface{}, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := e.channel.Send("evalOnSelectorAll", map[string]interface{}{
+ "selector": selector,
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(result), nil
+}
+
+func (e *elementHandleImpl) ScrollIntoViewIfNeeded(options ...ElementHandleScrollIntoViewIfNeededOptions) error {
+ _, err := e.channel.Send("scrollIntoViewIfNeeded", options)
+ if err != nil {
+ return err
+ }
+ return err
+}
+
+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
+}
+
+func (e *elementHandleImpl) BoundingBox() (*Rect, error) {
+ boundingBox, err := e.channel.Send("boundingBox")
+ if err != nil {
+ return nil, err
+ }
+
+ if boundingBox == nil {
+ return nil, nil
+ }
+
+ out := &Rect{}
+ remapMapToStruct(boundingBox, out)
+ return out, nil
+}
+
+func (e *elementHandleImpl) Check(options ...ElementHandleCheckOptions) error {
+ _, err := e.channel.Send("check", options)
+ return err
+}
+
+func (e *elementHandleImpl) Uncheck(options ...ElementHandleUncheckOptions) error {
+ _, err := e.channel.Send("uncheck", options)
+ return err
+}
+
+func (e *elementHandleImpl) Press(key string, options ...ElementHandlePressOptions) error {
+ _, err := e.channel.Send("press", map[string]interface{}{
+ "key": key,
+ }, options)
+ return err
+}
+
+func (e *elementHandleImpl) Fill(value string, options ...ElementHandleFillOptions) error {
+ _, err := e.channel.Send("fill", map[string]interface{}{
+ "value": value,
+ }, options)
+ return err
+}
+
+func (e *elementHandleImpl) Type(value string, options ...ElementHandleTypeOptions) error {
+ _, err := e.channel.Send("type", map[string]interface{}{
+ "text": value,
+ }, options)
+ return err
+}
+
+func (e *elementHandleImpl) Focus() error {
+ _, err := e.channel.Send("focus")
+ return err
+}
+
+func (e *elementHandleImpl) SelectText(options ...ElementHandleSelectTextOptions) error {
+ _, err := e.channel.Send("selectText", options)
+ return err
+}
+
+func (e *elementHandleImpl) Screenshot(options ...ElementHandleScreenshotOptions) ([]byte, error) {
+ var path *string
+ overrides := map[string]interface{}{}
+ if len(options) == 1 {
+ path = options[0].Path
+ options[0].Path = nil
+ if options[0].Mask != nil {
+ masks := make([]map[string]interface{}, 0)
+ for _, m := range options[0].Mask {
+ if m.Err() != nil { // ErrLocatorNotSameFrame
+ return nil, m.Err()
+ }
+ l, ok := m.(*locatorImpl)
+ if ok {
+ masks = append(masks, map[string]interface{}{
+ "selector": l.selector,
+ "frame": l.frame.channel,
+ })
+ }
+ }
+ overrides["mask"] = masks
+ options[0].Mask = nil
+ }
+ }
+ data, err := e.channel.Send("screenshot", options, overrides)
+ if err != nil {
+ 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, 0o644); err != nil {
+ return nil, err
+ }
+ }
+ return image, nil
+}
+
+func (e *elementHandleImpl) Tap(options ...ElementHandleTapOptions) error {
+ _, err := e.channel.Send("tap", options)
+ return err
+}
+
+func (e *elementHandleImpl) SelectOption(values SelectOptionValues, options ...ElementHandleSelectOptionOptions) ([]string, error) {
+ opts := convertSelectOptionSet(values)
+ selected, err := e.channel.Send("selectOption", opts, options)
+ if err != nil {
+ return nil, err
+ }
+
+ return transformToStringList(selected), nil
+}
+
+func (e *elementHandleImpl) IsChecked() (bool, error) {
+ checked, err := e.channel.Send("isChecked")
+ if err != nil {
+ return false, err
+ }
+ return checked.(bool), nil
+}
+
+func (e *elementHandleImpl) IsDisabled() (bool, error) {
+ disabled, err := e.channel.Send("isDisabled")
+ if err != nil {
+ return false, err
+ }
+ return disabled.(bool), nil
+}
+
+func (e *elementHandleImpl) IsEditable() (bool, error) {
+ editable, err := e.channel.Send("isEditable")
+ if err != nil {
+ return false, err
+ }
+ return editable.(bool), nil
+}
+
+func (e *elementHandleImpl) IsEnabled() (bool, error) {
+ enabled, err := e.channel.Send("isEnabled")
+ if err != nil {
+ return false, err
+ }
+ return enabled.(bool), nil
+}
+
+func (e *elementHandleImpl) IsHidden() (bool, error) {
+ hidden, err := e.channel.Send("isHidden")
+ if err != nil {
+ return false, err
+ }
+ return hidden.(bool), nil
+}
+
+func (e *elementHandleImpl) IsVisible() (bool, error) {
+ visible, err := e.channel.Send("isVisible")
+ if err != nil {
+ return false, err
+ }
+ return visible.(bool), nil
+}
+
+func (e *elementHandleImpl) WaitForElementState(state ElementState, options ...ElementHandleWaitForElementStateOptions) error {
+ _, err := e.channel.Send("waitForElementState", map[string]interface{}{
+ "state": state,
+ }, options)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (e *elementHandleImpl) WaitForSelector(selector string, options ...ElementHandleWaitForSelectorOptions) (ElementHandle, error) {
+ ch, err := e.channel.Send("waitForSelector", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return nil, err
+ }
+
+ channelOwner := fromNullableChannel(ch)
+ if channelOwner == nil {
+ return nil, nil
+ }
+ return channelOwner.(*elementHandleImpl), nil
+}
+
+func (e *elementHandleImpl) InputValue(options ...ElementHandleInputValueOptions) (string, error) {
+ result, err := e.channel.Send("inputValue", options)
+ if result == nil {
+ return "", err
+ }
+ return result.(string), err
+}
+
+func (e *elementHandleImpl) SetChecked(checked bool, options ...ElementHandleSetCheckedOptions) error {
+ if checked {
+ _, err := e.channel.Send("check", options)
+ return err
+ } else {
+ _, err := e.channel.Send("uncheck", options)
+ return err
+ }
+}
+
+func newElementHandle(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *elementHandleImpl {
+ bt := &elementHandleImpl{}
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ return bt
+}
+
+func transformToStringList(in interface{}) []string {
+ s := in.([]interface{})
+
+ var out []string
+ for _, v := range s {
+ out = append(out, v.(string))
+ }
+ return out
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/errors.go b/vendor/github.com/playwright-community/playwright-go/errors.go
new file mode 100644
index 0000000..36f7396
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/errors.go
@@ -0,0 +1,58 @@
+package playwright
+
+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 {
+ Name string `json:"name"`
+ Message string `json:"message"`
+ Stack string `json:"stack"`
+}
+
+func (e *Error) Error() string {
+ return e.Message
+}
+
+func (e *Error) Is(target error) bool {
+ err, ok := target.(*Error)
+ if !ok {
+ return false
+ }
+ if err.Name != e.Name {
+ return false
+ }
+ if e.Name != "Error" {
+ return true // same name and not normal error
+ }
+ return e.Message == err.Message
+}
+
+func parseError(err Error) error {
+ 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)
+}
+
+func targetClosedError(reason *string) error {
+ if reason == nil {
+ return ErrTargetClosed
+ }
+ 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
new file mode 100644
index 0000000..d4d62ef
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/event_emitter.go
@@ -0,0 +1,163 @@
+package playwright
+
+import (
+ "math"
+ "reflect"
+ "slices"
+ "sync"
+)
+
+type EventEmitter interface {
+ Emit(name string, payload ...interface{}) bool
+ ListenerCount(name string) int
+ On(name string, handler interface{})
+ Once(name string, handler interface{})
+ RemoveListener(name string, handler interface{})
+ RemoveListeners(name string)
+}
+
+type (
+ eventEmitter struct {
+ eventsMutex sync.Mutex
+ events map[string]*eventRegister
+ hasInit bool
+ }
+ eventRegister struct {
+ sync.Mutex
+ listeners []listener
+ }
+ listener struct {
+ handler interface{}
+ once bool
+ }
+)
+
+func NewEventEmitter() EventEmitter {
+ return &eventEmitter{}
+}
+
+func (e *eventEmitter) Emit(name string, payload ...interface{}) (hasListener bool) {
+ e.eventsMutex.Lock()
+ e.init()
+
+ evt, ok := e.events[name]
+ if !ok {
+ e.eventsMutex.Unlock()
+ return
+ }
+ e.eventsMutex.Unlock()
+ return evt.callHandlers(payload...) > 0
+}
+
+func (e *eventEmitter) Once(name string, handler interface{}) {
+ e.addEvent(name, handler, true)
+}
+
+func (e *eventEmitter) On(name string, handler interface{}) {
+ e.addEvent(name, handler, false)
+}
+
+func (e *eventEmitter) RemoveListener(name string, handler interface{}) {
+ e.eventsMutex.Lock()
+ defer e.eventsMutex.Unlock()
+ e.init()
+
+ if evt, ok := e.events[name]; ok {
+ evt.Lock()
+ defer evt.Unlock()
+ evt.removeHandler(handler)
+ }
+}
+
+func (e *eventEmitter) RemoveListeners(name string) {
+ e.eventsMutex.Lock()
+ defer e.eventsMutex.Unlock()
+ e.init()
+ delete(e.events, name)
+}
+
+// ListenerCount count the listeners by name, count all if name is empty
+func (e *eventEmitter) ListenerCount(name string) int {
+ e.eventsMutex.Lock()
+ defer e.eventsMutex.Unlock()
+ e.init()
+
+ if name != "" {
+ evt, ok := e.events[name]
+ if !ok {
+ return 0
+ }
+ return evt.count()
+ }
+
+ 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{
+ listeners: make([]listener, 0),
+ }
+ }
+ e.events[name].addHandler(handler, once)
+}
+
+func (e *eventEmitter) init() {
+ if !e.hasInit {
+ e.events = make(map[string]*eventRegister, 0)
+ e.hasInit = true
+ }
+}
+
+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 (er *eventRegister) removeHandler(handler interface{}) {
+ handlerPtr := reflect.ValueOf(handler).Pointer()
+
+ er.listeners = slices.DeleteFunc(er.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
new file mode 100644
index 0000000..fc7f79f
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/fetch.go
@@ -0,0 +1,451 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "os"
+ "strings"
+)
+
+type apiRequestImpl struct {
+ *Playwright
+}
+
+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
+ }
+ if options[0].StorageStatePath != nil {
+ var storageState *StorageState
+ storageString, err := os.ReadFile(*options[0].StorageStatePath)
+ if err != nil {
+ return nil, fmt.Errorf("could not read storage state file: %w", err)
+ }
+ err = json.Unmarshal(storageString, &storageState)
+ if err != nil {
+ return nil, fmt.Errorf("could not parse storage state file: %w", err)
+ }
+ options[0].StorageState = storageState
+ options[0].StorageStatePath = nil
+ }
+ }
+
+ channel, err := r.channel.Send("newRequest", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(channel).(*apiRequestContextImpl), nil
+}
+
+func newApiRequestImpl(pw *Playwright) *apiRequestImpl {
+ return &apiRequestImpl{pw}
+}
+
+type apiRequestContextImpl struct {
+ channelOwner
+ tracing *tracingImpl
+ closeReason *string
+}
+
+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
+}
+
+func (r *apiRequestContextImpl) Delete(url string, options ...APIRequestContextDeleteOptions) (APIResponse, error) {
+ opts := APIRequestContextFetchOptions{
+ Method: String("DELETE"),
+ }
+ if len(options) == 1 {
+ err := assignStructFields(&opts, options[0], false)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return r.Fetch(url, opts)
+}
+
+func (r *apiRequestContextImpl) Fetch(urlOrRequest interface{}, options ...APIRequestContextFetchOptions) (APIResponse, error) {
+ switch v := urlOrRequest.(type) {
+ case string:
+ return r.innerFetch(v, nil, options...)
+ case Request:
+ return r.innerFetch("", v, options...)
+ default:
+ return nil, fmt.Errorf("urlOrRequest has unsupported type: %T", urlOrRequest)
+ }
+}
+
+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
+ } else if request != nil {
+ overrides["url"] = request.URL()
+ }
+
+ if len(options) == 1 {
+ 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")
+ }
+ if options[0].Method == nil {
+ if request != nil {
+ options[0].Method = String(request.Method())
+ } else {
+ options[0].Method = String("GET")
+ }
+ }
+ if options[0].Headers == nil {
+ if request != nil {
+ overrides["headers"] = serializeMapToNameAndValue(request.Headers())
+ }
+ } else {
+ overrides["headers"] = serializeMapToNameAndValue(options[0].Headers)
+ options[0].Headers = nil
+ }
+ if options[0].Data != nil {
+ switch v := options[0].Data.(type) {
+ case string:
+ headersArray, ok := overrides["headers"].([]map[string]string)
+ if ok && isJsonContentType(headersArray) {
+ 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))
+ }
+ case []byte:
+ overrides["postData"] = base64.StdEncoding.EncodeToString(v)
+ case interface{}:
+ data, err := json.Marshal(v)
+ if err != nil {
+ return nil, fmt.Errorf("could not marshal data: %w", err)
+ }
+ overrides["jsonData"] = string(data)
+ default:
+ return nil, errors.New("data must be a string, []byte, or interface{} that can marshal to json")
+ }
+ options[0].Data = nil
+ } else if options[0].Form != nil {
+ form, ok := options[0].Form.(map[string]interface{})
+ if !ok {
+ return nil, errors.New("form must be a map")
+ }
+ overrides["formData"] = serializeMapToNameValue(form)
+ options[0].Form = nil
+ } else if options[0].Multipart != nil {
+ _, ok := options[0].Multipart.(map[string]interface{})
+ if !ok {
+ return nil, errors.New("multipart must be a map")
+ }
+ multipartData := []map[string]interface{}{}
+ for name, value := range options[0].Multipart.(map[string]interface{}) {
+ switch v := value.(type) {
+ case InputFile:
+ multipartData = append(multipartData, map[string]interface{}{
+ "name": name,
+ "file": map[string]string{
+ "name": v.Name,
+ "mimeType": v.MimeType,
+ "buffer": base64.StdEncoding.EncodeToString(v.Buffer),
+ },
+ })
+ default:
+ multipartData = append(multipartData, map[string]interface{}{
+ "name": name,
+ "value": String(fmt.Sprintf("%v", v)),
+ })
+ }
+ }
+ overrides["multipartData"] = multipartData
+ options[0].Multipart = nil
+ } else if request != nil {
+ postDataBuf, err := request.PostDataBuffer()
+ if err == nil {
+ overrides["postData"] = base64.StdEncoding.EncodeToString(postDataBuf)
+ }
+ }
+ if options[0].Params != nil {
+ overrides["params"] = serializeMapToNameValue(options[0].Params)
+ options[0].Params = nil
+ }
+ }
+
+ response, err := r.channel.Send("fetch", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+
+ return newAPIResponse(r, response.(map[string]interface{})), nil
+}
+
+func (r *apiRequestContextImpl) Get(url string, options ...APIRequestContextGetOptions) (APIResponse, error) {
+ opts := APIRequestContextFetchOptions{
+ Method: String("GET"),
+ }
+ if len(options) == 1 {
+ err := assignStructFields(&opts, options[0], false)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return r.Fetch(url, opts)
+}
+
+func (r *apiRequestContextImpl) Head(url string, options ...APIRequestContextHeadOptions) (APIResponse, error) {
+ opts := APIRequestContextFetchOptions{
+ Method: String("HEAD"),
+ }
+ if len(options) == 1 {
+ err := assignStructFields(&opts, options[0], false)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return r.Fetch(url, opts)
+}
+
+func (r *apiRequestContextImpl) Patch(url string, options ...APIRequestContextPatchOptions) (APIResponse, error) {
+ opts := APIRequestContextFetchOptions{
+ Method: String("PATCH"),
+ }
+ if len(options) == 1 {
+ err := assignStructFields(&opts, options[0], false)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return r.Fetch(url, opts)
+}
+
+func (r *apiRequestContextImpl) Put(url string, options ...APIRequestContextPutOptions) (APIResponse, error) {
+ opts := APIRequestContextFetchOptions{
+ Method: String("PUT"),
+ }
+ if len(options) == 1 {
+ err := assignStructFields(&opts, options[0], false)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return r.Fetch(url, opts)
+}
+
+func (r *apiRequestContextImpl) Post(url string, options ...APIRequestContextPostOptions) (APIResponse, error) {
+ opts := APIRequestContextFetchOptions{
+ Method: String("POST"),
+ }
+ if len(options) == 1 {
+ err := assignStructFields(&opts, options[0], false)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return r.Fetch(url, opts)
+}
+
+func (r *apiRequestContextImpl) StorageState(path ...string) (*StorageState, error) {
+ result, err := r.channel.SendReturnAsDict("storageState")
+ if err != nil {
+ return nil, err
+ }
+ if len(path) == 1 {
+ file, err := os.Create(path[0])
+ if err != nil {
+ return nil, err
+ }
+ if err := json.NewEncoder(file).Encode(result); err != nil {
+ return nil, err
+ }
+ if err := file.Close(); err != nil {
+ return nil, err
+ }
+ }
+ var storageState StorageState
+ remapMapToStruct(result, &storageState)
+ return &storageState, nil
+}
+
+func newAPIRequestContext(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *apiRequestContextImpl {
+ rc := &apiRequestContextImpl{}
+ rc.createChannelOwner(rc, parent, objectType, guid, initializer)
+ rc.tracing = fromChannel(initializer["tracing"]).(*tracingImpl)
+ return rc
+}
+
+type apiResponseImpl struct {
+ request *apiRequestContextImpl
+ initializer map[string]interface{}
+ headers *rawHeaders
+}
+
+func (r *apiResponseImpl) Body() ([]byte, error) {
+ result, err := r.request.channel.SendReturnAsDict("fetchResponseBody", []map[string]interface{}{
+ {
+ "fetchUid": r.fetchUid(),
+ },
+ })
+ if err != nil {
+ if errors.Is(err, ErrTargetClosed) {
+ return nil, errors.New("response has been disposed")
+ }
+ return nil, err
+ }
+ body := result["binary"]
+ if body == nil {
+ return nil, errors.New("response has been disposed")
+ }
+ return base64.StdEncoding.DecodeString(body.(string))
+}
+
+func (r *apiResponseImpl) Dispose() error {
+ _, err := r.request.channel.Send("disposeAPIResponse", []map[string]interface{}{
+ {
+ "fetchUid": r.fetchUid(),
+ },
+ })
+ return err
+}
+
+func (r *apiResponseImpl) Headers() map[string]string {
+ return r.headers.Headers()
+}
+
+func (r *apiResponseImpl) HeadersArray() []NameValue {
+ return r.headers.HeadersArray()
+}
+
+func (r *apiResponseImpl) JSON(v interface{}) error {
+ body, err := r.Body()
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(body, &v)
+}
+
+func (r *apiResponseImpl) Ok() bool {
+ return r.Status() == 0 || (r.Status() >= 200 && r.Status() <= 299)
+}
+
+func (r *apiResponseImpl) Status() int {
+ return int(r.initializer["status"].(float64))
+}
+
+func (r *apiResponseImpl) StatusText() string {
+ return r.initializer["statusText"].(string)
+}
+
+func (r *apiResponseImpl) Text() (string, error) {
+ body, err := r.Body()
+ if err != nil {
+ return "", err
+ }
+ return string(body), nil
+}
+
+func (r *apiResponseImpl) URL() string {
+ return r.initializer["url"].(string)
+}
+
+func (r *apiResponseImpl) fetchUid() string {
+ return r.initializer["fetchUid"].(string)
+}
+
+func (r *apiResponseImpl) fetchLog() ([]string, error) {
+ ret, err := r.request.channel.Send("fetchLog", map[string]interface{}{
+ "fetchUid": r.fetchUid(),
+ })
+ if err != nil {
+ return nil, err
+ }
+ result := make([]string, len(ret.([]interface{})))
+ for i, v := range ret.([]interface{}) {
+ result[i] = v.(string)
+ }
+ return result, nil
+}
+
+func newAPIResponse(context *apiRequestContextImpl, initializer map[string]interface{}) *apiResponseImpl {
+ return &apiResponseImpl{
+ request: context,
+ initializer: initializer,
+ headers: newRawHeaders(initializer["headers"]),
+ }
+}
+
+func countNonNil(args ...interface{}) int {
+ count := 0
+ for _, v := range args {
+ if v != nil {
+ count++
+ }
+ }
+ return count
+}
+
+func isJsonContentType(headers []map[string]string) bool {
+ if len(headers) > 0 {
+ for _, v := range headers {
+ if strings.ToLower(v["name"]) == "content-type" {
+ if v["value"] == "application/json" {
+ return true
+ }
+ }
+ }
+ }
+ return false
+}
+
+func serializeMapToNameValue(data map[string]interface{}) []map[string]string {
+ serialized := make([]map[string]string, 0, len(data))
+ for k, v := range data {
+ serialized = append(serialized, map[string]string{
+ "name": k,
+ "value": fmt.Sprintf("%v", v),
+ })
+ }
+ return serialized
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/file_chooser.go b/vendor/github.com/playwright-community/playwright-go/file_chooser.go
new file mode 100644
index 0000000..119e885
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/file_chooser.go
@@ -0,0 +1,44 @@
+package playwright
+
+type fileChooserImpl struct {
+ page Page
+ elementHandle ElementHandle
+ isMultiple bool
+}
+
+func (f *fileChooserImpl) Page() Page {
+ return f.page
+}
+
+func (f *fileChooserImpl) Element() ElementHandle {
+ return f.elementHandle
+}
+
+func (f *fileChooserImpl) IsMultiple() bool {
+ return f.isMultiple
+}
+
+// InputFile represents the input file for:
+// - FileChooser.SetFiles()
+// - ElementHandle.SetInputFiles()
+// - Page.SetInputFiles()
+type InputFile struct {
+ Name string `json:"name"`
+ MimeType string `json:"mimeType,omitempty"`
+ Buffer []byte `json:"buffer"`
+}
+
+func (f *fileChooserImpl) SetFiles(files interface{}, options ...FileChooserSetFilesOptions) error {
+ if len(options) == 1 {
+ return f.elementHandle.SetInputFiles(files, ElementHandleSetInputFilesOptions(options[0]))
+ }
+ return f.elementHandle.SetInputFiles(files)
+}
+
+func newFileChooser(page Page, elementHandle ElementHandle, isMultiple bool) *fileChooserImpl {
+ return &fileChooserImpl{
+ page: page,
+ elementHandle: elementHandle,
+ isMultiple: isMultiple,
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/frame.go b/vendor/github.com/playwright-community/playwright-go/frame.go
new file mode 100644
index 0000000..b571c8e
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/frame.go
@@ -0,0 +1,792 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "time"
+
+ mapset "github.com/deckarep/golang-set/v2"
+)
+
+type frameImpl struct {
+ channelOwner
+ detached bool
+ page *pageImpl
+ name string
+ url string
+ parentFrame Frame
+ childFrames []Frame
+ loadStates mapset.Set[string]
+}
+
+func newFrame(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *frameImpl {
+ var loadStates mapset.Set[string]
+
+ if ls, ok := initializer["loadStates"].([]string); ok {
+ loadStates = mapset.NewSet[string](ls...)
+ } else {
+ loadStates = mapset.NewSet[string]()
+ }
+ f := &frameImpl{
+ name: initializer["name"].(string),
+ url: initializer["url"].(string),
+ loadStates: loadStates,
+ childFrames: make([]Frame, 0),
+ }
+ f.createChannelOwner(f, parent, objectType, guid, initializer)
+
+ channelOwner := fromNullableChannel(initializer["parentFrame"])
+ if channelOwner != nil {
+ f.parentFrame = channelOwner.(*frameImpl)
+ f.parentFrame.(*frameImpl).childFrames = append(f.parentFrame.(*frameImpl).childFrames, f)
+ }
+
+ f.channel.On("navigated", f.onFrameNavigated)
+ f.channel.On("loadstate", f.onLoadState)
+ return f
+}
+
+func (f *frameImpl) URL() string {
+ f.RLock()
+ defer f.RUnlock()
+ return f.url
+}
+
+func (f *frameImpl) Name() string {
+ f.RLock()
+ defer f.RUnlock()
+ return f.name
+}
+
+func (f *frameImpl) SetContent(content string, options ...FrameSetContentOptions) error {
+ _, err := f.channel.Send("setContent", map[string]interface{}{
+ "html": content,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) Content() (string, error) {
+ content, err := f.channel.Send("content")
+ if content == nil {
+ return "", err
+ }
+ return content.(string), err
+}
+
+func (f *frameImpl) Goto(url string, options ...FrameGotoOptions) (Response, error) {
+ channel, err := f.channel.Send("goto", map[string]interface{}{
+ "url": url,
+ }, options)
+ if err != nil {
+ return nil, fmt.Errorf("Frame.Goto %s: %w", url, err)
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ // navigation to about:blank or navigation to the same URL with a different hash
+ return nil, nil
+ }
+ return channelOwner.(*responseImpl), nil
+}
+
+func (f *frameImpl) AddScriptTag(options FrameAddScriptTagOptions) (ElementHandle, error) {
+ if options.Path != nil {
+ file, err := os.ReadFile(*options.Path)
+ if err != nil {
+ return nil, err
+ }
+ options.Content = String(string(file))
+ options.Path = nil
+ }
+ channel, err := f.channel.Send("addScriptTag", options)
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(channel).(*elementHandleImpl), nil
+}
+
+func (f *frameImpl) AddStyleTag(options FrameAddStyleTagOptions) (ElementHandle, error) {
+ if options.Path != nil {
+ file, err := os.ReadFile(*options.Path)
+ if err != nil {
+ return nil, err
+ }
+ options.Content = String(string(file))
+ options.Path = nil
+ }
+ channel, err := f.channel.Send("addStyleTag", options)
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(channel).(*elementHandleImpl), nil
+}
+
+func (f *frameImpl) Page() Page {
+ return f.page
+}
+
+func (f *frameImpl) WaitForLoadState(options ...FrameWaitForLoadStateOptions) error {
+ option := FrameWaitForLoadStateOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ if option.State == nil {
+ option.State = LoadStateLoad
+ }
+ return f.waitForLoadStateImpl(string(*option.State), option.Timeout, nil)
+}
+
+func (f *frameImpl) waitForLoadStateImpl(state string, timeout *float64, cb func() error) error {
+ if f.loadStates.ContainsOne(state) {
+ return nil
+ }
+ waiter, err := f.setNavigationWaiter(timeout)
+ if err != nil {
+ return err
+ }
+ waiter.WaitForEvent(f, "loadstate", func(payload interface{}) bool {
+ gotState := payload.(string)
+ return gotState == state
+ })
+ if cb == nil {
+ _, err := waiter.Wait()
+ return err
+ } else {
+ _, err := waiter.RunAndWait(cb)
+ return err
+ }
+}
+
+func (f *frameImpl) WaitForURL(url interface{}, options ...FrameWaitForURLOptions) error {
+ if f.page == nil {
+ return errors.New("frame is detached")
+ }
+ matcher := newURLMatcher(url, f.page.browserContext.options.BaseURL)
+ if matcher.Matches(f.URL()) {
+ state := "load"
+ timeout := Float(f.page.timeoutSettings.NavigationTimeout())
+ if len(options) == 1 {
+ if options[0].WaitUntil != nil {
+ state = string(*options[0].WaitUntil)
+ }
+ if options[0].Timeout != nil {
+ timeout = options[0].Timeout
+ }
+ }
+ return f.waitForLoadStateImpl(state, timeout, nil)
+ }
+ navigationOptions := FrameExpectNavigationOptions{URL: url}
+ if len(options) > 0 {
+ navigationOptions.Timeout = options[0].Timeout
+ navigationOptions.WaitUntil = options[0].WaitUntil
+ }
+ if _, err := f.ExpectNavigation(nil, navigationOptions); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (f *frameImpl) ExpectNavigation(cb func() error, options ...FrameExpectNavigationOptions) (Response, error) {
+ if f.page == nil {
+ return nil, errors.New("frame is detached")
+ }
+ option := FrameExpectNavigationOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ if option.WaitUntil == nil {
+ option.WaitUntil = WaitUntilStateLoad
+ }
+ if option.Timeout == nil {
+ option.Timeout = Float(f.page.timeoutSettings.NavigationTimeout())
+ }
+ deadline := time.Now().Add(time.Duration(*option.Timeout) * time.Millisecond)
+ var matcher *urlMatcher
+ if option.URL != nil {
+ matcher = newURLMatcher(option.URL, f.page.browserContext.options.BaseURL)
+ }
+ predicate := func(events ...interface{}) bool {
+ ev := events[0].(map[string]interface{})
+ err, ok := ev["error"]
+ if ok {
+ // Any failed navigation results in a rejection.
+ logger.Error("navigation error", "url", ev["url"].(string), "error", err)
+ return true
+ }
+ return matcher == nil || matcher.Matches(ev["url"].(string))
+ }
+ waiter, err := f.setNavigationWaiter(option.Timeout)
+ if err != nil {
+ return nil, err
+ }
+
+ eventData, err := waiter.WaitForEvent(f, "navigated", predicate).RunAndWait(cb)
+ if err != nil || eventData == nil {
+ return nil, err
+ }
+
+ t := time.Until(deadline).Milliseconds()
+ if t > 0 {
+ err = f.waitForLoadStateImpl(string(*option.WaitUntil), Float(float64(t)), nil)
+ if err != nil {
+ return nil, err
+ }
+ }
+ event := eventData.(map[string]interface{})
+ if event["newDocument"] != nil && event["newDocument"].(map[string]interface{})["request"] != nil {
+ request := fromChannel(event["newDocument"].(map[string]interface{})["request"]).(*requestImpl)
+ return request.Response()
+ }
+ return nil, nil
+}
+
+func (f *frameImpl) setNavigationWaiter(timeout *float64) (*waiter, error) {
+ if f.page == nil {
+ return nil, errors.New("page does not exist")
+ }
+ waiter := newWaiter()
+ if timeout != nil {
+ waiter.WithTimeout(*timeout)
+ } else {
+ waiter.WithTimeout(f.page.timeoutSettings.NavigationTimeout())
+ }
+ 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)
+ if ok && frame == f {
+ return true
+ }
+ return false
+ })
+ return waiter, nil
+}
+
+func (f *frameImpl) onFrameNavigated(ev map[string]interface{}) {
+ f.Lock()
+ f.url = ev["url"].(string)
+ f.name = ev["name"].(string)
+ f.Unlock()
+ f.Emit("navigated", ev)
+ _, ok := ev["error"]
+ if !ok && f.page != nil {
+ f.page.Emit("framenavigated", f)
+ }
+}
+
+func (f *frameImpl) onLoadState(ev map[string]interface{}) {
+ if ev["add"] != nil {
+ add := ev["add"].(string)
+ f.loadStates.Add(add)
+ f.Emit("loadstate", add)
+ if f.parentFrame == nil && f.page != nil {
+ if add == "load" || add == "domcontentloaded" {
+ f.Page().Emit(add, f.page)
+ }
+ }
+ } else if ev["remove"] != nil {
+ remove := ev["remove"].(string)
+ f.loadStates.Remove(remove)
+ }
+}
+
+func (f *frameImpl) QuerySelector(selector string, options ...FrameQuerySelectorOptions) (ElementHandle, error) {
+ params := map[string]interface{}{
+ "selector": selector,
+ }
+ if len(options) == 1 {
+ params["strict"] = options[0].Strict
+ }
+ channel, err := f.channel.Send("querySelector", params)
+ if err != nil {
+ return nil, err
+ }
+ if channel == nil {
+ return nil, nil
+ }
+ return fromChannel(channel).(*elementHandleImpl), nil
+}
+
+func (f *frameImpl) QuerySelectorAll(selector string) ([]ElementHandle, error) {
+ channels, err := f.channel.Send("querySelectorAll", map[string]interface{}{
+ "selector": selector,
+ })
+ if err != nil {
+ return nil, err
+ }
+ elements := make([]ElementHandle, 0)
+ for _, channel := range channels.([]interface{}) {
+ elements = append(elements, fromChannel(channel).(*elementHandleImpl))
+ }
+ return elements, nil
+}
+
+func (f *frameImpl) Evaluate(expression string, options ...interface{}) (interface{}, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := f.channel.Send("evaluateExpression", map[string]interface{}{
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(result), nil
+}
+
+func (f *frameImpl) EvalOnSelector(selector string, expression string, arg interface{}, options ...FrameEvalOnSelectorOptions) (interface{}, error) {
+ params := map[string]interface{}{
+ "selector": selector,
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ }
+ if len(options) == 1 && options[0].Strict != nil {
+ params["strict"] = *options[0].Strict
+ }
+
+ result, err := f.channel.Send("evalOnSelector", params)
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(result), nil
+}
+
+func (f *frameImpl) EvalOnSelectorAll(selector string, expression string, options ...interface{}) (interface{}, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := f.channel.Send("evalOnSelectorAll", map[string]interface{}{
+ "selector": selector,
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(result), nil
+}
+
+func (f *frameImpl) EvaluateHandle(expression string, options ...interface{}) (JSHandle, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := f.channel.Send("evaluateExpressionHandle", map[string]interface{}{
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromChannel(result)
+ if channelOwner == nil {
+ return nil, nil
+ }
+ return channelOwner.(JSHandle), nil
+}
+
+func (f *frameImpl) Click(selector string, options ...FrameClickOptions) error {
+ _, err := f.channel.Send("click", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) WaitForSelector(selector string, options ...FrameWaitForSelectorOptions) (ElementHandle, error) {
+ channel, err := f.channel.Send("waitForSelector", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ return nil, nil
+ }
+ return channelOwner.(*elementHandleImpl), nil
+}
+
+func (f *frameImpl) DispatchEvent(selector, typ string, eventInit interface{}, options ...FrameDispatchEventOptions) error {
+ _, err := f.channel.Send("dispatchEvent", map[string]interface{}{
+ "selector": selector,
+ "type": typ,
+ "eventInit": serializeArgument(eventInit),
+ })
+ return err
+}
+
+func (f *frameImpl) InnerText(selector string, options ...FrameInnerTextOptions) (string, error) {
+ innerText, err := f.channel.Send("innerText", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if innerText == nil {
+ return "", err
+ }
+ return innerText.(string), err
+}
+
+func (f *frameImpl) InnerHTML(selector string, options ...FrameInnerHTMLOptions) (string, error) {
+ innerHTML, err := f.channel.Send("innerHTML", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if innerHTML == nil {
+ return "", err
+ }
+ return innerHTML.(string), err
+}
+
+func (f *frameImpl) GetAttribute(selector string, name string, options ...FrameGetAttributeOptions) (string, error) {
+ attribute, err := f.channel.Send("getAttribute", map[string]interface{}{
+ "selector": selector,
+ "name": name,
+ }, options)
+ if attribute == nil {
+ return "", err
+ }
+ return attribute.(string), err
+}
+
+func (f *frameImpl) Hover(selector string, options ...FrameHoverOptions) error {
+ _, err := f.channel.Send("hover", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+}
+
+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
+}
+
+func (f *frameImpl) Type(selector, text string, options ...FrameTypeOptions) error {
+ _, err := f.channel.Send("type", map[string]interface{}{
+ "selector": selector,
+ "text": text,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) Press(selector, key string, options ...FramePressOptions) error {
+ _, err := f.channel.Send("press", map[string]interface{}{
+ "selector": selector,
+ "key": key,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) Check(selector string, options ...FrameCheckOptions) error {
+ _, err := f.channel.Send("check", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) Uncheck(selector string, options ...FrameUncheckOptions) error {
+ _, err := f.channel.Send("uncheck", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) WaitForTimeout(timeout float64) {
+ time.Sleep(time.Duration(timeout) * time.Millisecond)
+}
+
+func (f *frameImpl) WaitForFunction(expression string, arg interface{}, options ...FrameWaitForFunctionOptions) (JSHandle, error) {
+ var option FrameWaitForFunctionOptions
+ if len(options) == 1 {
+ option = options[0]
+ }
+ result, err := f.channel.Send("waitForFunction", map[string]interface{}{
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ "timeout": option.Timeout,
+ "polling": option.Polling,
+ })
+ if err != nil {
+ return nil, err
+ }
+ handle := fromChannel(result)
+ if handle == nil {
+ return nil, nil
+ }
+ return handle.(*jsHandleImpl), nil
+}
+
+func (f *frameImpl) Title() (string, error) {
+ title, err := f.channel.Send("title")
+ if title == nil {
+ return "", err
+ }
+ return title.(string), err
+}
+
+func (f *frameImpl) ChildFrames() []Frame {
+ return f.childFrames
+}
+
+func (f *frameImpl) Dblclick(selector string, options ...FrameDblclickOptions) error {
+ _, err := f.channel.Send("dblclick", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) Fill(selector string, value string, options ...FrameFillOptions) error {
+ _, err := f.channel.Send("fill", map[string]interface{}{
+ "selector": selector,
+ "value": value,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) Focus(selector string, options ...FrameFocusOptions) error {
+ _, err := f.channel.Send("focus", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) FrameElement() (ElementHandle, error) {
+ channel, err := f.channel.Send("frameElement")
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(channel).(*elementHandleImpl), nil
+}
+
+func (f *frameImpl) IsDetached() bool {
+ return f.detached
+}
+
+func (f *frameImpl) ParentFrame() Frame {
+ return f.parentFrame
+}
+
+func (f *frameImpl) TextContent(selector string, options ...FrameTextContentOptions) (string, error) {
+ textContent, err := f.channel.Send("textContent", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if textContent == nil {
+ return "", err
+ }
+ return textContent.(string), err
+}
+
+func (f *frameImpl) Tap(selector string, options ...FrameTapOptions) error {
+ _, err := f.channel.Send("tap", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) SelectOption(selector string, values SelectOptionValues, options ...FrameSelectOptionOptions) ([]string, error) {
+ opts := convertSelectOptionSet(values)
+
+ m := make(map[string]interface{})
+ m["selector"] = selector
+ for k, v := range opts {
+ m[k] = v
+ }
+ selected, err := f.channel.Send("selectOption", m, options)
+ if err != nil {
+ return nil, err
+ }
+
+ return transformToStringList(selected), nil
+}
+
+func (f *frameImpl) IsChecked(selector string, options ...FrameIsCheckedOptions) (bool, error) {
+ checked, err := f.channel.Send("isChecked", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return false, err
+ }
+ return checked.(bool), nil
+}
+
+func (f *frameImpl) IsDisabled(selector string, options ...FrameIsDisabledOptions) (bool, error) {
+ disabled, err := f.channel.Send("isDisabled", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return false, err
+ }
+ return disabled.(bool), nil
+}
+
+func (f *frameImpl) IsEditable(selector string, options ...FrameIsEditableOptions) (bool, error) {
+ editable, err := f.channel.Send("isEditable", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return false, err
+ }
+ return editable.(bool), nil
+}
+
+func (f *frameImpl) IsEnabled(selector string, options ...FrameIsEnabledOptions) (bool, error) {
+ enabled, err := f.channel.Send("isEnabled", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return false, err
+ }
+ return enabled.(bool), nil
+}
+
+func (f *frameImpl) IsHidden(selector string, options ...FrameIsHiddenOptions) (bool, error) {
+ hidden, err := f.channel.Send("isHidden", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return false, err
+ }
+ return hidden.(bool), nil
+}
+
+func (f *frameImpl) IsVisible(selector string, options ...FrameIsVisibleOptions) (bool, error) {
+ visible, err := f.channel.Send("isVisible", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return false, err
+ }
+ return visible.(bool), nil
+}
+
+func (f *frameImpl) InputValue(selector string, options ...FrameInputValueOptions) (string, error) {
+ value, err := f.channel.Send("inputValue", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if value == nil {
+ return "", err
+ }
+ return value.(string), err
+}
+
+func (f *frameImpl) DragAndDrop(source, target string, options ...FrameDragAndDropOptions) error {
+ _, err := f.channel.Send("dragAndDrop", map[string]interface{}{
+ "source": source,
+ "target": target,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) SetChecked(selector string, checked bool, options ...FrameSetCheckedOptions) error {
+ if checked {
+ _, err := f.channel.Send("check", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+ } else {
+ _, err := f.channel.Send("uncheck", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+ }
+}
+
+func (f *frameImpl) Locator(selector string, options ...FrameLocatorOptions) Locator {
+ var option LocatorOptions
+ if len(options) == 1 {
+ option = LocatorOptions{
+ Has: options[0].Has,
+ HasNot: options[0].HasNot,
+ HasText: options[0].HasText,
+ HasNotText: options[0].HasNotText,
+ }
+ }
+ return newLocator(f, selector, option)
+}
+
+func (f *frameImpl) GetByAltText(text interface{}, options ...FrameGetByAltTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return f.Locator(getByAltTextSelector(text, exact))
+}
+
+func (f *frameImpl) GetByLabel(text interface{}, options ...FrameGetByLabelOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return f.Locator(getByLabelSelector(text, exact))
+}
+
+func (f *frameImpl) GetByPlaceholder(text interface{}, options ...FrameGetByPlaceholderOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return f.Locator(getByPlaceholderSelector(text, exact))
+}
+
+func (f *frameImpl) GetByRole(role AriaRole, options ...FrameGetByRoleOptions) Locator {
+ if len(options) == 1 {
+ return f.Locator(getByRoleSelector(role, LocatorGetByRoleOptions(options[0])))
+ }
+ return f.Locator(getByRoleSelector(role))
+}
+
+func (f *frameImpl) GetByTestId(testId interface{}) Locator {
+ return f.Locator(getByTestIdSelector(getTestIdAttributeName(), testId))
+}
+
+func (f *frameImpl) GetByText(text interface{}, options ...FrameGetByTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return f.Locator(getByTextSelector(text, exact))
+}
+
+func (f *frameImpl) GetByTitle(text interface{}, options ...FrameGetByTitleOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return f.Locator(getByTitleSelector(text, exact))
+}
+
+func (f *frameImpl) FrameLocator(selector string) FrameLocator {
+ return newFrameLocator(f, selector)
+}
+
+func (f *frameImpl) highlight(selector string) error {
+ _, err := f.channel.Send("highlight", map[string]interface{}{
+ "selector": selector,
+ })
+ return err
+}
+
+func (f *frameImpl) queryCount(selector string) (int, error) {
+ response, err := f.channel.Send("queryCount", map[string]interface{}{
+ "selector": selector,
+ })
+ if err != nil {
+ return 0, err
+ }
+ return int(response.(float64)), nil
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/frame_locator.go b/vendor/github.com/playwright-community/playwright-go/frame_locator.go
new file mode 100644
index 0000000..d4b8fd0
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/frame_locator.go
@@ -0,0 +1,130 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+)
+
+type frameLocatorImpl struct {
+ frame *frameImpl
+ frameSelector string
+}
+
+func newFrameLocator(frame *frameImpl, frameSelector string) *frameLocatorImpl {
+ return &frameLocatorImpl{frame: frame, frameSelector: frameSelector}
+}
+
+func (fl *frameLocatorImpl) First() FrameLocator {
+ return newFrameLocator(fl.frame, fl.frameSelector+" >> nth=0")
+}
+
+func (fl *frameLocatorImpl) FrameLocator(selector string) FrameLocator {
+ return newFrameLocator(fl.frame, fl.frameSelector+" >> internal:control=enter-frame >> "+selector)
+}
+
+func (fl *frameLocatorImpl) GetByAltText(text interface{}, options ...FrameLocatorGetByAltTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return fl.Locator(getByAltTextSelector(text, exact))
+}
+
+func (fl *frameLocatorImpl) GetByLabel(text interface{}, options ...FrameLocatorGetByLabelOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return fl.Locator(getByLabelSelector(text, exact))
+}
+
+func (fl *frameLocatorImpl) GetByPlaceholder(text interface{}, options ...FrameLocatorGetByPlaceholderOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return fl.Locator(getByPlaceholderSelector(text, exact))
+}
+
+func (fl *frameLocatorImpl) GetByRole(role AriaRole, options ...FrameLocatorGetByRoleOptions) Locator {
+ if len(options) == 1 {
+ return fl.Locator(getByRoleSelector(role, LocatorGetByRoleOptions(options[0])))
+ }
+ return fl.Locator(getByRoleSelector(role))
+}
+
+func (fl *frameLocatorImpl) GetByTestId(testId interface{}) Locator {
+ return fl.Locator(getByTestIdSelector(getTestIdAttributeName(), testId))
+}
+
+func (fl *frameLocatorImpl) GetByText(text interface{}, options ...FrameLocatorGetByTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return fl.Locator(getByTextSelector(text, exact))
+}
+
+func (fl *frameLocatorImpl) GetByTitle(text interface{}, options ...FrameLocatorGetByTitleOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return fl.Locator(getByTitleSelector(text, exact))
+}
+
+func (fl *frameLocatorImpl) Last() FrameLocator {
+ return newFrameLocator(fl.frame, fl.frameSelector+" >> nth=-1")
+}
+
+func (fl *frameLocatorImpl) Locator(selectorOrLocator interface{}, options ...FrameLocatorLocatorOptions) Locator {
+ var option LocatorOptions
+ if len(options) == 1 {
+ option = LocatorOptions{
+ Has: options[0].Has,
+ HasNot: options[0].HasNot,
+ HasText: options[0].HasText,
+ HasNotText: options[0].HasNotText,
+ }
+ }
+
+ selector, ok := selectorOrLocator.(string)
+ if ok {
+ return newLocator(fl.frame, fl.frameSelector+" >> internal:control=enter-frame >> "+selector, option)
+ }
+ locator, ok := selectorOrLocator.(*locatorImpl)
+ if ok {
+ if fl.frame != locator.frame {
+ locator.err = errors.Join(locator.err, ErrLocatorNotSameFrame)
+ return locator
+ }
+ return newLocator(locator.frame,
+ fmt.Sprintf("%s >> internal:control=enter-frame >> %s", fl.frameSelector, locator.selector),
+ option,
+ )
+ }
+ return &locatorImpl{
+ frame: fl.frame,
+ selector: fl.frameSelector,
+ err: fmt.Errorf("invalid locator parameter: %v", selectorOrLocator),
+ }
+}
+
+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
new file mode 100644
index 0000000..92c20c6
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/generated-enums.go
@@ -0,0 +1,404 @@
+package playwright
+
+func getMixedState(in string) *MixedState {
+ v := MixedState(in)
+ return &v
+}
+
+type MixedState string
+
+var (
+ MixedStateOn *MixedState = getMixedState("On")
+ MixedStateOff = getMixedState("Off")
+ MixedStateMixed = getMixedState("Mixed")
+)
+
+func getElementState(in string) *ElementState {
+ v := ElementState(in)
+ return &v
+}
+
+type ElementState string
+
+var (
+ ElementStateVisible *ElementState = getElementState("visible")
+ ElementStateHidden = getElementState("hidden")
+ ElementStateStable = getElementState("stable")
+ ElementStateEnabled = getElementState("enabled")
+ ElementStateDisabled = getElementState("disabled")
+ ElementStateEditable = getElementState("editable")
+)
+
+func getAriaRole(in string) *AriaRole {
+ v := AriaRole(in)
+ return &v
+}
+
+type AriaRole string
+
+var (
+ AriaRoleAlert *AriaRole = getAriaRole("alert")
+ AriaRoleAlertdialog = getAriaRole("alertdialog")
+ AriaRoleApplication = getAriaRole("application")
+ AriaRoleArticle = getAriaRole("article")
+ AriaRoleBanner = getAriaRole("banner")
+ AriaRoleBlockquote = getAriaRole("blockquote")
+ AriaRoleButton = getAriaRole("button")
+ AriaRoleCaption = getAriaRole("caption")
+ AriaRoleCell = getAriaRole("cell")
+ AriaRoleCheckbox = getAriaRole("checkbox")
+ AriaRoleCode = getAriaRole("code")
+ AriaRoleColumnheader = getAriaRole("columnheader")
+ AriaRoleCombobox = getAriaRole("combobox")
+ AriaRoleComplementary = getAriaRole("complementary")
+ AriaRoleContentinfo = getAriaRole("contentinfo")
+ AriaRoleDefinition = getAriaRole("definition")
+ AriaRoleDeletion = getAriaRole("deletion")
+ AriaRoleDialog = getAriaRole("dialog")
+ AriaRoleDirectory = getAriaRole("directory")
+ AriaRoleDocument = getAriaRole("document")
+ AriaRoleEmphasis = getAriaRole("emphasis")
+ AriaRoleFeed = getAriaRole("feed")
+ AriaRoleFigure = getAriaRole("figure")
+ AriaRoleForm = getAriaRole("form")
+ AriaRoleGeneric = getAriaRole("generic")
+ AriaRoleGrid = getAriaRole("grid")
+ AriaRoleGridcell = getAriaRole("gridcell")
+ AriaRoleGroup = getAriaRole("group")
+ AriaRoleHeading = getAriaRole("heading")
+ AriaRoleImg = getAriaRole("img")
+ AriaRoleInsertion = getAriaRole("insertion")
+ AriaRoleLink = getAriaRole("link")
+ AriaRoleList = getAriaRole("list")
+ AriaRoleListbox = getAriaRole("listbox")
+ AriaRoleListitem = getAriaRole("listitem")
+ AriaRoleLog = getAriaRole("log")
+ AriaRoleMain = getAriaRole("main")
+ AriaRoleMarquee = getAriaRole("marquee")
+ AriaRoleMath = getAriaRole("math")
+ AriaRoleMeter = getAriaRole("meter")
+ AriaRoleMenu = getAriaRole("menu")
+ AriaRoleMenubar = getAriaRole("menubar")
+ AriaRoleMenuitem = getAriaRole("menuitem")
+ AriaRoleMenuitemcheckbox = getAriaRole("menuitemcheckbox")
+ AriaRoleMenuitemradio = getAriaRole("menuitemradio")
+ AriaRoleNavigation = getAriaRole("navigation")
+ AriaRoleNone = getAriaRole("none")
+ AriaRoleNote = getAriaRole("note")
+ AriaRoleOption = getAriaRole("option")
+ AriaRoleParagraph = getAriaRole("paragraph")
+ AriaRolePresentation = getAriaRole("presentation")
+ AriaRoleProgressbar = getAriaRole("progressbar")
+ AriaRoleRadio = getAriaRole("radio")
+ AriaRoleRadiogroup = getAriaRole("radiogroup")
+ AriaRoleRegion = getAriaRole("region")
+ AriaRoleRow = getAriaRole("row")
+ AriaRoleRowgroup = getAriaRole("rowgroup")
+ AriaRoleRowheader = getAriaRole("rowheader")
+ AriaRoleScrollbar = getAriaRole("scrollbar")
+ AriaRoleSearch = getAriaRole("search")
+ AriaRoleSearchbox = getAriaRole("searchbox")
+ AriaRoleSeparator = getAriaRole("separator")
+ AriaRoleSlider = getAriaRole("slider")
+ AriaRoleSpinbutton = getAriaRole("spinbutton")
+ AriaRoleStatus = getAriaRole("status")
+ AriaRoleStrong = getAriaRole("strong")
+ AriaRoleSubscript = getAriaRole("subscript")
+ AriaRoleSuperscript = getAriaRole("superscript")
+ AriaRoleSwitch = getAriaRole("switch")
+ AriaRoleTab = getAriaRole("tab")
+ AriaRoleTable = getAriaRole("table")
+ AriaRoleTablist = getAriaRole("tablist")
+ AriaRoleTabpanel = getAriaRole("tabpanel")
+ AriaRoleTerm = getAriaRole("term")
+ AriaRoleTextbox = getAriaRole("textbox")
+ AriaRoleTime = getAriaRole("time")
+ AriaRoleTimer = getAriaRole("timer")
+ AriaRoleToolbar = getAriaRole("toolbar")
+ AriaRoleTooltip = getAriaRole("tooltip")
+ AriaRoleTree = getAriaRole("tree")
+ AriaRoleTreegrid = getAriaRole("treegrid")
+ AriaRoleTreeitem = getAriaRole("treeitem")
+)
+
+func getColorScheme(in string) *ColorScheme {
+ v := ColorScheme(in)
+ return &v
+}
+
+type ColorScheme string
+
+var (
+ ColorSchemeLight *ColorScheme = getColorScheme("light")
+ ColorSchemeDark = getColorScheme("dark")
+ ColorSchemeNoPreference = getColorScheme("no-preference")
+ ColorSchemeNoOverride = getColorScheme("no-override")
+)
+
+func getForcedColors(in string) *ForcedColors {
+ v := ForcedColors(in)
+ return &v
+}
+
+type ForcedColors string
+
+var (
+ ForcedColorsActive *ForcedColors = getForcedColors("active")
+ ForcedColorsNone = getForcedColors("none")
+ ForcedColorsNoOverride = getForcedColors("no-override")
+)
+
+func getHarContentPolicy(in string) *HarContentPolicy {
+ v := HarContentPolicy(in)
+ return &v
+}
+
+type HarContentPolicy string
+
+var (
+ HarContentPolicyOmit *HarContentPolicy = getHarContentPolicy("omit")
+ HarContentPolicyEmbed = getHarContentPolicy("embed")
+ HarContentPolicyAttach = getHarContentPolicy("attach")
+)
+
+func getHarMode(in string) *HarMode {
+ v := HarMode(in)
+ return &v
+}
+
+type HarMode string
+
+var (
+ HarModeFull *HarMode = getHarMode("full")
+ HarModeMinimal = getHarMode("minimal")
+)
+
+func getReducedMotion(in string) *ReducedMotion {
+ v := ReducedMotion(in)
+ return &v
+}
+
+type ReducedMotion string
+
+var (
+ ReducedMotionReduce *ReducedMotion = getReducedMotion("reduce")
+ ReducedMotionNoPreference = getReducedMotion("no-preference")
+ ReducedMotionNoOverride = getReducedMotion("no-override")
+)
+
+func getServiceWorkerPolicy(in string) *ServiceWorkerPolicy {
+ v := ServiceWorkerPolicy(in)
+ return &v
+}
+
+type ServiceWorkerPolicy string
+
+var (
+ ServiceWorkerPolicyAllow *ServiceWorkerPolicy = getServiceWorkerPolicy("allow")
+ ServiceWorkerPolicyBlock = getServiceWorkerPolicy("block")
+)
+
+func getSameSiteAttribute(in string) *SameSiteAttribute {
+ v := SameSiteAttribute(in)
+ return &v
+}
+
+type SameSiteAttribute string
+
+var (
+ SameSiteAttributeStrict *SameSiteAttribute = getSameSiteAttribute("Strict")
+ SameSiteAttributeLax = getSameSiteAttribute("Lax")
+ SameSiteAttributeNone = getSameSiteAttribute("None")
+)
+
+func getHarNotFound(in string) *HarNotFound {
+ v := HarNotFound(in)
+ return &v
+}
+
+type HarNotFound string
+
+var (
+ HarNotFoundAbort *HarNotFound = getHarNotFound("abort")
+ HarNotFoundFallback = getHarNotFound("fallback")
+)
+
+func getRouteFromHarUpdateContentPolicy(in string) *RouteFromHarUpdateContentPolicy {
+ v := RouteFromHarUpdateContentPolicy(in)
+ return &v
+}
+
+type RouteFromHarUpdateContentPolicy string
+
+var (
+ RouteFromHarUpdateContentPolicyEmbed *RouteFromHarUpdateContentPolicy = getRouteFromHarUpdateContentPolicy("embed")
+ 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
+}
+
+type MouseButton string
+
+var (
+ MouseButtonLeft *MouseButton = getMouseButton("left")
+ MouseButtonRight = getMouseButton("right")
+ MouseButtonMiddle = getMouseButton("middle")
+)
+
+func getKeyboardModifier(in string) *KeyboardModifier {
+ v := KeyboardModifier(in)
+ return &v
+}
+
+type KeyboardModifier string
+
+var (
+ KeyboardModifierAlt *KeyboardModifier = getKeyboardModifier("Alt")
+ KeyboardModifierControl = getKeyboardModifier("Control")
+ KeyboardModifierControlOrMeta = getKeyboardModifier("ControlOrMeta")
+ KeyboardModifierMeta = getKeyboardModifier("Meta")
+ KeyboardModifierShift = getKeyboardModifier("Shift")
+)
+
+func getScreenshotAnimations(in string) *ScreenshotAnimations {
+ v := ScreenshotAnimations(in)
+ return &v
+}
+
+type ScreenshotAnimations string
+
+var (
+ ScreenshotAnimationsDisabled *ScreenshotAnimations = getScreenshotAnimations("disabled")
+ ScreenshotAnimationsAllow = getScreenshotAnimations("allow")
+)
+
+func getScreenshotCaret(in string) *ScreenshotCaret {
+ v := ScreenshotCaret(in)
+ return &v
+}
+
+type ScreenshotCaret string
+
+var (
+ ScreenshotCaretHide *ScreenshotCaret = getScreenshotCaret("hide")
+ ScreenshotCaretInitial = getScreenshotCaret("initial")
+)
+
+func getScreenshotScale(in string) *ScreenshotScale {
+ v := ScreenshotScale(in)
+ return &v
+}
+
+type ScreenshotScale string
+
+var (
+ ScreenshotScaleCss *ScreenshotScale = getScreenshotScale("css")
+ ScreenshotScaleDevice = getScreenshotScale("device")
+)
+
+func getScreenshotType(in string) *ScreenshotType {
+ v := ScreenshotType(in)
+ return &v
+}
+
+type ScreenshotType string
+
+var (
+ ScreenshotTypePng *ScreenshotType = getScreenshotType("png")
+ ScreenshotTypeJpeg = getScreenshotType("jpeg")
+)
+
+func getWaitForSelectorState(in string) *WaitForSelectorState {
+ v := WaitForSelectorState(in)
+ return &v
+}
+
+type WaitForSelectorState string
+
+var (
+ WaitForSelectorStateAttached *WaitForSelectorState = getWaitForSelectorState("attached")
+ WaitForSelectorStateDetached = getWaitForSelectorState("detached")
+ WaitForSelectorStateVisible = getWaitForSelectorState("visible")
+ WaitForSelectorStateHidden = getWaitForSelectorState("hidden")
+)
+
+func getWaitUntilState(in string) *WaitUntilState {
+ v := WaitUntilState(in)
+ return &v
+}
+
+type WaitUntilState string
+
+var (
+ WaitUntilStateLoad *WaitUntilState = getWaitUntilState("load")
+ WaitUntilStateDomcontentloaded = getWaitUntilState("domcontentloaded")
+ WaitUntilStateNetworkidle = getWaitUntilState("networkidle")
+ WaitUntilStateCommit = getWaitUntilState("commit")
+)
+
+func getLoadState(in string) *LoadState {
+ v := LoadState(in)
+ return &v
+}
+
+type LoadState string
+
+var (
+ LoadStateLoad *LoadState = getLoadState("load")
+ LoadStateDomcontentloaded = getLoadState("domcontentloaded")
+ LoadStateNetworkidle = getLoadState("networkidle")
+)
+
+func getContrast(in string) *Contrast {
+ v := Contrast(in)
+ return &v
+}
+
+type Contrast string
+
+var (
+ ContrastNoPreference *Contrast = getContrast("no-preference")
+ ContrastMore = getContrast("more")
+ ContrastNoOverride = getContrast("no-override")
+)
+
+func getMedia(in string) *Media {
+ v := Media(in)
+ return &v
+}
+
+type Media string
+
+var (
+ MediaScreen *Media = getMedia("screen")
+ 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
new file mode 100644
index 0000000..187dc91
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/generated-interfaces.go
@@ -0,0 +1,4658 @@
+package playwright
+
+// Exposes API that can be used for the Web API testing. This class is used for creating [APIRequestContext] instance
+// which in turn can be used for sending web requests. An instance of this class can be obtained via
+// [Playwright.Request]. For more information see [APIRequestContext].
+type APIRequest interface {
+ // Creates new instances of [APIRequestContext].
+ NewContext(options ...APIRequestNewContextOptions) (APIRequestContext, error)
+}
+
+// This API is used for the Web API testing. You can use it to trigger API endpoints, configure micro-services,
+// prepare environment or the service to your e2e test.
+// Each Playwright browser context has associated with it [APIRequestContext] instance which shares cookie storage
+// with the browser context and can be accessed via [BrowserContext.Request] or [Page.Request]. It is also possible to
+// create a new APIRequestContext instance manually by calling [APIRequest.NewContext].
+// **Cookie management**
+// [APIRequestContext] returned by [BrowserContext.Request] and [Page.Request] shares cookie storage with the
+// corresponding [BrowserContext]. Each API request will have `Cookie` header populated with the values from the
+// browser context. If the API response contains `Set-Cookie` header it will automatically update [BrowserContext]
+// cookies and requests made from the page will pick them up. This means that if you log in using this API, your e2e
+// test will be logged in and vice versa.
+// If you want API requests to not interfere with the browser cookies you should create a new [APIRequestContext] by
+// calling [APIRequest.NewContext]. Such `APIRequestContext` object will have its own isolated cookie storage.
+type APIRequestContext interface {
+ // Sends HTTP(S) [DELETE] 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.
+ //
+ // url: Target URL.
+ //
+ // [DELETE]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE
+ 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 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.
+ //
+ // urlOrRequest: Target URL or Request to get all parameters from.
+ Fetch(urlOrRequest interface{}, options ...APIRequestContextFetchOptions) (APIResponse, error)
+
+ // Sends HTTP(S) [GET] 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.
+ //
+ // url: Target URL.
+ //
+ // [GET]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET
+ Get(url string, options ...APIRequestContextGetOptions) (APIResponse, error)
+
+ // Sends HTTP(S) [HEAD] 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.
+ //
+ // url: Target URL.
+ //
+ // [HEAD]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD
+ Head(url string, options ...APIRequestContextHeadOptions) (APIResponse, error)
+
+ // Sends HTTP(S) [PATCH] 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.
+ //
+ // url: Target URL.
+ //
+ // [PATCH]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH
+ Patch(url string, options ...APIRequestContextPatchOptions) (APIResponse, error)
+
+ // Sends HTTP(S) [POST] 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.
+ //
+ // url: Target URL.
+ //
+ // [POST]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST
+ Post(url string, options ...APIRequestContextPostOptions) (APIResponse, error)
+
+ // Sends HTTP(S) [PUT] 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.
+ //
+ // url: Target URL.
+ //
+ // [PUT]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT
+ Put(url string, options ...APIRequestContextPutOptions) (APIResponse, error)
+
+ // Returns storage state for this request context, contains current cookies and local storage snapshot if it was
+ // passed to the constructor.
+ StorageState(path ...string) (*StorageState, error)
+}
+
+// [APIResponse] class represents responses returned by [APIRequestContext.Get] and similar methods.
+type APIResponse interface {
+ // Returns the buffer with response body.
+ Body() ([]byte, error)
+
+ // Disposes the body of this response. If not called then the body will stay in memory until the context closes.
+ Dispose() error
+
+ // An object with all the response HTTP headers associated with this response.
+ Headers() map[string]string
+
+ // 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.
+ // This method will throw if the response body is not parsable via `JSON.parse`.
+ JSON(v interface{}) error
+
+ // Contains a boolean stating whether the response was successful (status in the range 200-299) or not.
+ Ok() bool
+
+ // Contains the status code of the response (e.g., 200 for a success).
+ Status() int
+
+ // Contains the status text of the response (e.g. usually an "OK" for a success).
+ StatusText() string
+
+ // Returns the text representation of response body.
+ Text() (string, error)
+
+ // Contains the URL of the response.
+ URL() string
+}
+
+// The [APIResponseAssertions] class provides assertion methods that can be used to make assertions about the
+// [APIResponse] in the tests.
+type APIResponseAssertions interface {
+ // Makes the assertion check for the opposite condition. For example, this code tests that the response status is not
+ // successful:
+ Not() APIResponseAssertions
+
+ // Ensures the response status code is within `200..299` range.
+ ToBeOK() error
+}
+
+// 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
+ // following:
+ // - Browser application is closed or crashed.
+ // - The [Browser.Close] method was called.
+ OnDisconnected(fn func(Browser))
+
+ // Get the browser type (chromium, firefox or webkit) that the browser belongs to.
+ BrowserType() BrowserType
+
+ // In case this browser is obtained using [BrowserType.Launch], closes the browser and all of its pages (if any were
+ // opened).
+ // In case this browser is connected to, clears all created contexts belonging to this browser and disconnects from
+ // the browser server.
+ // **NOTE** This is similar to force-quitting the browser. To close pages gracefully and ensure you receive page close
+ // events, call [BrowserContext.Close] on any [BrowserContext] instances you explicitly created earlier using
+ // [Browser.NewContext] **before** calling [Browser.Close].
+ // The [Browser] object itself is considered to be disposed and cannot be used anymore.
+ 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
+
+ // Indicates that the browser is connected.
+ IsConnected() bool
+
+ // **NOTE** CDP Sessions are only supported on Chromium-based browsers.
+ // Returns the newly created browser session.
+ NewBrowserCDPSession() (CDPSession, error)
+
+ // Creates a new browser context. It won't share cookies/cache with other browser contexts.
+ // **NOTE** If directly using this method to create [BrowserContext]s, it is best practice to explicitly close the
+ // returned context via [BrowserContext.Close] when your code is done with the [BrowserContext], and before calling
+ // [Browser.Close]. This will ensure the `context` is closed gracefully and any artifacts—like HARs and videos—are
+ // fully flushed and saved.
+ NewContext(options ...BrowserNewContextOptions) (BrowserContext, error)
+
+ // Creates a new page in a new browser context. Closing this page will close the context as well.
+ // This is a convenience API that should only be used for the single-page scenarios and short snippets. Production
+ // code and testing frameworks should explicitly create [Browser.NewContext] followed by the [BrowserContext.NewPage]
+ // to control their exact life times.
+ NewPage(options ...BrowserNewPageOptions) (Page, error)
+
+ // **NOTE** This API controls
+ // [Chromium Tracing] which is a low-level
+ // chromium-specific debugging tool. API to control [Playwright Tracing] could be found
+ // [here].
+ // You can use [Browser.StartTracing] and [Browser.StopTracing] to create a trace file that can be opened in Chrome
+ // DevTools performance panel.
+ //
+ // [Chromium Tracing]: https://www.chromium.org/developers/how-tos/trace-event-profiling-tool
+ // [Playwright Tracing]: ../trace-viewer
+ // [here]: ./class-tracing
+ StartTracing(options ...BrowserStartTracingOptions) error
+
+ // **NOTE** This API controls
+ // [Chromium Tracing] which is a low-level
+ // chromium-specific debugging tool. API to control [Playwright Tracing] could be found
+ // [here].
+ // Returns the buffer with trace data.
+ //
+ // [Chromium Tracing]: https://www.chromium.org/developers/how-tos/trace-event-profiling-tool
+ // [Playwright Tracing]: ../trace-viewer
+ // [here]: ./class-tracing
+ StopTracing() ([]byte, error)
+
+ // Returns the browser version.
+ Version() string
+}
+
+// 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 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`.
+ // The arguments passed into `console.log` and the page are available on the [ConsoleMessage] event handler argument.
+ OnConsole(fn func(ConsoleMessage))
+
+ // Emitted when a JavaScript dialog appears, such as `alert`, `prompt`, `confirm` or `beforeunload`. Listener **must**
+ // either [Dialog.Accept] or [Dialog.Dismiss] the dialog - otherwise the page will
+ // [freeze] waiting for the dialog,
+ // and actions like click will never finish.
+ //
+ // [freeze]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking
+ OnDialog(fn func(Dialog))
+
+ // The event is emitted when a new Page is created in the BrowserContext. The page may still be loading. The event
+ // 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. 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))
+
+ // Emitted when exception is unhandled in any of the pages in this context. To listen for errors from a particular
+ // page, use [Page.OnPageError] instead.
+ OnWebError(fn func(WebError))
+
+ // Emitted when a request is issued from any pages created through this context. The [request] object is read-only. To
+ // only listen for requests from a particular page, use [Page.OnRequest].
+ // In order to intercept and mutate requests, see [BrowserContext.Route] or [Page.Route].
+ OnRequest(fn func(Request))
+
+ // Emitted when a request fails, for example by timing out. To only listen for failed requests from a particular page,
+ // use [Page.OnRequestFailed].
+ // **NOTE** HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request
+ // will complete with [BrowserContext.OnRequestFinished] event and not with [BrowserContext.OnRequestFailed].
+ OnRequestFailed(fn func(Request))
+
+ // Emitted when a request finishes successfully after downloading the response body. For a successful response, the
+ // sequence of events is `request`, `response` and `requestfinished`. To listen for successful requests from a
+ // particular page, use [Page.OnRequestFinished].
+ OnRequestFinished(fn func(Request))
+
+ // Emitted when [response] status and headers are received for a request. For a successful response, the sequence of
+ // events is `request`, `response` and `requestfinished`. To listen for response events from a particular page, use
+ // [Page.OnResponse].
+ OnResponse(fn func(Response))
+
+ // Adds cookies into this browser context. All pages within this context will have these cookies installed. Cookies
+ // can be obtained via [BrowserContext.Cookies].
+ AddCookies(cookies []OptionalCookie) error
+
+ // Adds a script which would be evaluated in one of the following scenarios:
+ // - Whenever a page is created in the browser context or is navigated.
+ // - Whenever a child frame is attached or navigated in any page in the browser context. In this case, the script is
+ // evaluated in the context of the newly attached frame.
+ // The script is evaluated after the document was created but before any of its scripts were run. This is useful to
+ // amend the JavaScript environment, e.g. to seed `Math.random`.
+ //
+ // script: Script to be evaluated in all pages in the browser context.
+ AddInitScript(script Script) error
+
+ // **NOTE** Background pages are only supported on Chromium-based browsers.
+ // All existing background pages in the context.
+ BackgroundPages() []Page
+
+ // Returns the browser instance of the context. If it was launched as a persistent context null gets returned.
+ Browser() Browser
+
+ // 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(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.
+ Cookies(urls ...string) ([]Cookie, error)
+
+ // The method adds a function called “[object Object]” on the `window` object of every frame in every page in the
+ // context. When called, the function executes “[object Object]” and returns a [Promise] which resolves to the return
+ // value of “[object Object]”. If the “[object Object]” returns a [Promise], it will be awaited.
+ // The first argument of the “[object Object]” function contains information about the caller: `{ browserContext:
+ // BrowserContext, page: Page, frame: Frame }`.
+ // See [Page.ExposeBinding] for page-only version.
+ //
+ // 1. name: Name of the function on the window object.
+ // 2. binding: Callback function that will be called in the Playwright's context.
+ ExposeBinding(name string, binding BindingCallFunction, handle ...bool) error
+
+ // The method adds a function called “[object Object]” on the `window` object of every frame in every page in the
+ // context. When called, the function executes “[object Object]” and returns a [Promise] which resolves to the return
+ // value of “[object Object]”.
+ // If the “[object Object]” returns a [Promise], it will be awaited.
+ // See [Page.ExposeFunction] for page-only version.
+ //
+ // 1. name: Name of the function on the window object.
+ // 2. binding: Callback function that will be called in the Playwright's context.
+ ExposeFunction(name string, binding ExposedFunction) error
+
+ // Grants specified permissions to the browser context. Only grants corresponding permissions to the given origin if
+ // specified.
+ //
+ // permissions: A list of permissions to grant.
+ //
+ // **NOTE** Supported permissions differ between browsers, and even between different versions of the same browser.
+ // Any permission may stop working after an update.
+ //
+ // Here are some permissions that may be supported by some browsers:
+ // - `'accelerometer'`
+ // - `'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.
+ // Returns the newly created session.
+ //
+ // page: Target to create new session for. For backwards-compatibility, this parameter is named `page`, but it can be a
+ // `Page` or `Frame` type.
+ NewCDPSession(page interface{}) (CDPSession, error)
+
+ // Creates a new page in the browser context.
+ NewPage() (Page, error)
+
+ // Returns all open pages in the context.
+ Pages() []Page
+
+ // API testing helper associated with this context. Requests made with this API will use context cookies.
+ Request() APIRequestContext
+
+ // Routing provides the capability to modify network requests that are made by any page in the browser context. Once
+ // route is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted.
+ // **NOTE** [BrowserContext.Route] will not intercept requests intercepted by Service Worker. See
+ // [this] issue. We recommend disabling Service Workers when
+ // using request interception by setting “[object Object]” to `block`.
+ //
+ // 1. url: A glob pattern, regex pattern, or predicate that receives a [URL] to match during routing. If “[object Object]” is
+ // set in the context options and the provided URL is a string that does not start with `*`, it is resolved using the
+ // [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
+ // 2. handler: handler function to route the request.
+ //
+ // [this]: https://github.com/microsoft/playwright/issues/1090
+ Route(url interface{}, handler routeHandler, times ...int) error
+
+ // If specified the network requests that are made in the context will be served from the HAR file. Read more about
+ // [Replaying from HAR].
+ // Playwright will not serve requests intercepted by Service Worker from the HAR file. See
+ // [this] issue. We recommend disabling Service Workers when
+ // using request interception by setting “[object Object]” to `block`.
+ //
+ // har: Path to a [HAR](http://www.softwareishard.com/blog/har-12-spec) file with prerecorded network data. If `path` is a
+ // relative path, then it is resolved relative to the current working directory.
+ //
+ // [Replaying from HAR]: https://playwright.dev/docs/mock#replaying-from-har
+ // [this]: https://github.com/microsoft/playwright/issues/1090
+ RouteFromHAR(har string, options ...BrowserContextRouteFromHAROptions) error
+
+ // This method allows to modify websocket connections that are made by any page in the browser context.
+ // Note that only `WebSocket`s created after this method was called will be routed. It is recommended to call this
+ // method before creating any pages.
+ //
+ // 1. url: Only WebSockets with the url matching this pattern will be routed. A string pattern can be relative to the
+ // “[object Object]” context option.
+ // 2. handler: Handler function to route the WebSocket.
+ RouteWebSocket(url interface{}, handler func(WebSocketRoute)) error
+
+ // **NOTE** Service workers are only supported on Chromium-based browsers.
+ // All existing service workers in the context.
+ ServiceWorkers() []Worker
+
+ // This setting will change the default maximum navigation time for the following methods and related shortcuts:
+ // - [Page.GoBack]
+ // - [Page.GoForward]
+ // - [Page.Goto]
+ // - [Page.Reload]
+ // - [Page.SetContent]
+ // - [Page.ExpectNavigation]
+ // **NOTE** [Page.SetDefaultNavigationTimeout] and [Page.SetDefaultTimeout] take priority over
+ // [BrowserContext.SetDefaultNavigationTimeout].
+ //
+ // timeout: Maximum navigation time in milliseconds
+ SetDefaultNavigationTimeout(timeout float64)
+
+ // This setting will change the default maximum time for all the methods accepting “[object Object]” option.
+ // **NOTE** [Page.SetDefaultNavigationTimeout], [Page.SetDefaultTimeout] and
+ // [BrowserContext.SetDefaultNavigationTimeout] take priority over [BrowserContext.SetDefaultTimeout].
+ //
+ // timeout: Maximum time in milliseconds. Pass `0` to disable timeout.
+ SetDefaultTimeout(timeout float64)
+
+ // The extra HTTP headers will be sent with every request initiated by any page in the context. These headers are
+ // merged with page-specific extra HTTP headers set with [Page.SetExtraHTTPHeaders]. If page overrides a particular
+ // header, page-specific header value will be used instead of the browser context header value.
+ // **NOTE** [BrowserContext.SetExtraHTTPHeaders] does not guarantee the order of headers in the outgoing requests.
+ //
+ // headers: An object containing additional HTTP headers to be sent with every request. All header values must be strings.
+ SetExtraHTTPHeaders(headers map[string]string) error
+
+ // Sets the context's geolocation. Passing `null` or `undefined` emulates position unavailable.
+ SetGeolocation(geolocation *Geolocation) error
+
+ //
+ // offline: Whether to emulate network being offline for the browser context.
+ SetOffline(offline bool) error
+
+ // Returns storage state for this browser context, contains current cookies, local storage snapshot and IndexedDB
+ // snapshot.
+ StorageState(path ...string) (*StorageState, error)
+
+ Tracing() Tracing
+
+ // Removes all routes created with [BrowserContext.Route] and [BrowserContext.RouteFromHAR].
+ UnrouteAll(options ...BrowserContextUnrouteAllOptions) error
+
+ // Removes a route created with [BrowserContext.Route]. When “[object Object]” is not specified, removes all routes
+ // for the “[object Object]”.
+ //
+ // 1. url: A glob pattern, regex pattern or predicate receiving [URL] used to register a routing with [BrowserContext.Route].
+ // 2. handler: Optional handler function used to register a routing with [BrowserContext.Route].
+ Unroute(url interface{}, handler ...routeHandler) error
+
+ // Performs action and waits for a [ConsoleMessage] to be logged by in the pages in the context. If predicate is
+ // provided, it passes [ConsoleMessage] value into the `predicate` function and waits for `predicate(message)` to
+ // return a truthy value. Will throw an error if the page is closed before the [BrowserContext.OnConsole] event is
+ // fired.
+ ExpectConsoleMessage(cb func() error, options ...BrowserContextExpectConsoleMessageOptions) (ConsoleMessage, error)
+
+ // Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy
+ // value. Will throw an error if the context closes before the event is fired. Returns the event data value.
+ //
+ // event: Event name, same one would pass into `browserContext.on(event)`.
+ ExpectEvent(event string, cb func() error, options ...BrowserContextExpectEventOptions) (interface{}, error)
+
+ // Performs action and waits for a new [Page] to be created in the context. If predicate is provided, it passes [Page]
+ // value into the `predicate` function and waits for `predicate(event)` to return a truthy value. Will throw an error
+ // if the context closes before new [Page] is created.
+ ExpectPage(cb func() error, options ...BrowserContextExpectPageOptions) (Page, error)
+
+ // **NOTE** In most cases, you should use [BrowserContext.ExpectEvent].
+ // Waits for given `event` to fire. If predicate is provided, it passes event's value into the `predicate` function
+ // and waits for `predicate(event)` to return a truthy value. Will throw an error if the browser context is closed
+ // before the `event` is fired.
+ //
+ // event: Event name, same one typically passed into `*.on(event)`.
+ WaitForEvent(event string, options ...BrowserContextWaitForEventOptions) (interface{}, error)
+}
+
+// BrowserType provides methods to launch a specific browser instance or connect to an existing one. The following is
+// a typical example of using Playwright to drive automation:
+type BrowserType interface {
+ // This method attaches Playwright to an existing browser instance created via `BrowserType.launchServer` in Node.js.
+ // **NOTE** The major and minor version of the Playwright instance that connects needs to match the version of
+ // Playwright that launches the browser (1.2.3 → is compatible with 1.2.x).
+ //
+ // wsEndpoint: A Playwright browser websocket endpoint to connect to. You obtain this endpoint via `BrowserServer.wsEndpoint`.
+ Connect(wsEndpoint string, options ...BrowserTypeConnectOptions) (Browser, error)
+
+ // This method attaches Playwright to an existing browser instance using the Chrome DevTools Protocol.
+ // The default browser context is accessible via [Browser.Contexts].
+ // **NOTE** Connecting over the Chrome DevTools Protocol is only supported for Chromium-based browsers.
+ // **NOTE** This connection is significantly lower fidelity than the Playwright protocol connection via
+ // [BrowserType.Connect]. If you are experiencing issues or attempting to use advanced functionality, you probably
+ // want to use [BrowserType.Connect].
+ //
+ // endpointURL: A CDP websocket endpoint or http url to connect to. For example `http://localhost:9222/` or
+ // `ws://127.0.0.1:9222/devtools/browser/387adf4c-243f-4051-a181-46798f4a46f4`.
+ ConnectOverCDP(endpointURL string, options ...BrowserTypeConnectOverCDPOptions) (Browser, error)
+
+ // A path where Playwright expects to find a bundled browser executable.
+ ExecutablePath() string
+
+ // Returns the browser instance.
+ //
+ // [Chrome Canary]: https://www.google.com/chrome/browser/canary.html
+ // [Dev Channel]: https://www.chromium.org/getting-involved/dev-channel
+ // [this article]: https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/
+ // [This article]: https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md
+ Launch(options ...BrowserTypeLaunchOptions) (Browser, error)
+
+ // Returns the persistent browser context instance.
+ // Launches browser that uses persistent storage located at “[object Object]” and returns the only context. Closing
+ // this context will automatically close the browser.
+ //
+ // userDataDir: Path to a User Data Directory, which stores browser session data like cookies and local storage. Pass an empty
+ // string to create a temporary directory.
+ //
+ // More details for
+ // [Chromium](https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md#introduction) and
+ // [Firefox](https://wiki.mozilla.org/Firefox/CommandLineOptions#User_profile). Chromium's user data directory is the
+ // **parent** directory of the "Profile Path" seen at `chrome://version`.
+ //
+ // Note that browsers do not allow launching multiple instances with the same User Data Directory.
+ LaunchPersistentContext(userDataDir string, options ...BrowserTypeLaunchPersistentContextOptions) (BrowserContext, error)
+
+ // Returns browser name. For example: `chromium`, `webkit` or `firefox`.
+ 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.
+//
+// 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
+//
+// [DevTools Protocol Viewer]: https://chromedevtools.github.io/devtools-protocol/
+type CDPSession interface {
+ EventEmitter
+ // Detaches the CDPSession from the target. Once detached, the CDPSession object won't emit any events and can't be
+ // used to send messages.
+ Detach() error
+
+ //
+ // 1. method: Protocol method name.
+ // 2. params: Optional method parameters.
+ Send(method string, params map[string]interface{}) (interface{}, error)
+}
+
+// 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.
+ // Use this method for simple scenarios where you only need to test with a predefined time. For more advanced
+ // scenarios, use [Clock.Install] instead. Read docs on [clock emulation] to learn more.
+ //
+ // time: Time to be set.
+ //
+ // [clock emulation]: https://playwright.dev/docs/clock
+ SetFixedTime(time interface{}) error
+
+ // Sets system time, but does not trigger any timers. Use this to test how the web page reacts to a time shift, for
+ // example switching from summer to winter time, or changing time zones.
+ //
+ // 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].
+ Args() []JSHandle
+
+ Location() *ConsoleMessageLocation
+
+ // The page that produced this console message, if any.
+ Page() Page
+
+ // The text of the console message.
+ Text() string
+
+ // The text of the console message.
+ String() string
+
+ // One of the following values: `log`, `debug`, `info`, `error`, `warning`, `dir`, `dirxml`, `table`,
+ // `trace`, `clear`, `startGroup`, `startGroupCollapsed`, `endGroup`, `assert`, `profile`,
+ // `profileEnd`, `count`, `timeEnd`.
+ Type() string
+}
+
+// [Dialog] objects are dispatched by page via the [Page.OnDialog] event.
+// An example of using `Dialog` class:
+// **NOTE** Dialogs are dismissed automatically, unless there is a [Page.OnDialog] listener. When listener is present,
+// it **must** either [Dialog.Accept] or [Dialog.Dismiss] the dialog - otherwise the page will
+// [freeze] waiting for the dialog,
+// and actions like click will never finish.
+//
+// [freeze]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking
+type Dialog interface {
+ // Returns when the dialog has been accepted.
+ Accept(promptText ...string) error
+
+ // If dialog is prompt, returns default prompt value. Otherwise, returns empty string.
+ DefaultValue() string
+
+ // Returns when the dialog has been dismissed.
+ Dismiss() error
+
+ // A message displayed in the dialog.
+ Message() string
+
+ // The page that initiated this dialog, if available.
+ Page() Page
+
+ // Returns dialog's type, can be one of `alert`, `beforeunload`, `confirm` or `prompt`.
+ Type() string
+}
+
+// [Download] objects are dispatched by page via the [Page.OnDownload] event.
+// All the downloaded files belonging to the browser context are deleted when the browser context is closed.
+// Download event is emitted once the download starts. Download path becomes available once download completes.
+type Download interface {
+ // Cancels a download. Will not fail if the download is already finished or canceled. Upon successful cancellations,
+ // `download.failure()` would resolve to `canceled`.
+ Cancel() error
+
+ // Deletes the downloaded file. Will wait for the download to finish if necessary.
+ Delete() error
+
+ // Returns download error if any. Will wait for the download to finish if necessary.
+ Failure() error
+
+ // Get the page that the download belongs to.
+ Page() Page
+
+ // 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)
+
+ // Copy the download to a user-specified path. It is safe to call this method while the download is still in progress.
+ // Will wait for the download to finish if necessary.
+ //
+ // path: Path where the download should be copied.
+ SaveAs(path string) error
+
+ // Returns suggested filename for this download. It is typically computed by the browser from the
+ // [`Content-Disposition`] response
+ // header or the `download` attribute. See the spec on [whatwg].
+ // Different browsers can use different logic for computing it.
+ //
+ // [`Content-Disposition`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
+ // [whatwg]: https://html.spec.whatwg.org/#downloading-resources
+ SuggestedFilename() string
+
+ // Returns downloaded url.
+ URL() string
+
+ String() string
+}
+
+// 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].
+// ElementHandles are auto-disposed when their origin frame gets navigated.
+// ElementHandle instances can be used as an argument in [Page.EvalOnSelector] and [Page.Evaluate] methods.
+// The difference between the [Locator] and ElementHandle is that the ElementHandle points to a particular element,
+// while [Locator] captures the logic of how to retrieve an element.
+// In the example below, handle points to a particular DOM element on page. If that element changes text or is used by
+// React to render an entirely different component, handle is still pointing to that very DOM element. This can lead
+// to unexpected behaviors.
+// With the locator, every time the `element` is used, up-to-date DOM element is located in the page using the
+// selector. So in the snippet below, underlying DOM element is going to be located twice.
+type ElementHandle interface {
+ JSHandle
+ // This method returns the bounding box of the element, or `null` if the element is not visible. The bounding box is
+ // calculated relative to the main frame viewport - which is usually the same as the browser window.
+ // Scrolling affects the returned bounding box, similarly to
+ // [Element.GetBoundingClientRect].
+ // That means `x` and/or `y` may be negative.
+ // Elements from child frames return the bounding box relative to the main frame, unlike the
+ // [Element.GetBoundingClientRect].
+ // Assuming the page is static, it is safe to use bounding box coordinates to perform input. For example, the
+ // following snippet should click the center of the element.
+ //
+ // [Element.GetBoundingClientRect]: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
+ // [Element.GetBoundingClientRect]: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
+ BoundingBox() (*Rect, error)
+
+ // This method checks the element by performing the following steps:
+ // 1. Ensure that element is a checkbox or a radio input. If not, this method throws. If the element is already
+ // checked, this method returns immediately.
+ // 2. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to click in the center of the element.
+ // 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 “[object Object]”, 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:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 2. Scroll the element into view if needed.
+ // 3. Use [Page.Mouse] to click in the center of the element, or the specified “[object Object]”.
+ // 4. Wait for initiated navigations to either succeed or fail, unless “[object Object]” option is set.
+ // 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 “[object Object]”, 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
+ ContentFrame() (Frame, error)
+
+ // This method double clicks the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” 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 “[object Object]”.
+ // 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 “[object Object]”, 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
+ // [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 “[object Object]”.
+ // The method finds an element matching the specified selector in the `ElementHandle`s subtree and passes it as a
+ // first argument to “[object Object]”. If no elements match the selector, the method throws an error.
+ // If “[object Object]” 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.
+ // 3. arg: Optional argument to pass to “[object Object]”.
+ EvalOnSelector(selector string, expression string, arg ...interface{}) (interface{}, error)
+
+ // Returns the return value of “[object Object]”.
+ // The method finds all elements matching the specified selector in the `ElementHandle`'s subtree and passes an array
+ // of matched elements as a first argument to “[object Object]”.
+ // If “[object Object]” 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.
+ // 3. arg: Optional argument to pass to “[object Object]”.
+ EvalOnSelectorAll(selector string, expression string, arg ...interface{}) (interface{}, error)
+
+ // This method waits for [actionability] checks, focuses the element, fills it and triggers an
+ // `input` event after filling. Note that you can pass an empty string to clear the input field.
+ // If the target element is not an `<input>`, `<textarea>` or `[contenteditable]` element, this method throws an
+ // error. However, if the element is inside the `<label>` element that has an associated
+ // [control], the control will be filled
+ // 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 `<input>`, `<textarea>` or `[contenteditable]` element.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ Fill(value string, options ...ElementHandleFillOptions) error
+
+ // Calls [focus] on the element.
+ //
+ // Deprecated: Use locator-based [Locator.Focus] instead. Read more about [locators].
+ //
+ // [focus]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
+ // [locators]: https://playwright.dev/docs/locators
+ Focus() error
+
+ // Returns element attribute value.
+ //
+ // Deprecated: Use locator-based [Locator.GetAttribute] instead. Read more about [locators].
+ //
+ // name: Attribute name to get the value for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ GetAttribute(name string) (string, error)
+
+ // This method hovers over the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 2. Scroll the element into view if needed.
+ // 3. Use [Page.Mouse] to hover over the center of the element, or the specified “[object Object]”.
+ // 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 “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Hover] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Hover(options ...ElementHandleHoverOptions) error
+
+ // Returns the `element.innerHTML`.
+ //
+ // Deprecated: Use locator-based [Locator.InnerHTML] instead. Read more about [locators].
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ InnerHTML() (string, error)
+
+ // Returns the `element.innerText`.
+ //
+ // Deprecated: Use locator-based [Locator.InnerText] instead. Read more about [locators].
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ InnerText() (string, error)
+
+ // Returns `input.value` for the selected `<input>` or `<textarea>` or `<select>` element.
+ // Throws for non-input elements. However, if the element is inside the `<label>` element that has an associated
+ // [control], returns the value of the
+ // control.
+ //
+ // Deprecated: Use locator-based [Locator.InputValue] instead. Read more about [locators].
+ //
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ InputValue(options ...ElementHandleInputValueOptions) (string, error)
+
+ // Returns whether the element is checked. Throws if the element is not a checkbox or radio input.
+ //
+ // Deprecated: Use locator-based [Locator.IsChecked] instead. Read more about [locators].
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ IsChecked() (bool, error)
+
+ // Returns whether the element is disabled, the opposite of [enabled].
+ //
+ // Deprecated: Use locator-based [Locator.IsDisabled] instead. Read more about [locators].
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [locators]: https://playwright.dev/docs/locators
+ IsDisabled() (bool, error)
+
+ // Returns whether the element is [editable].
+ //
+ // Deprecated: Use locator-based [Locator.IsEditable] instead. Read more about [locators].
+ //
+ // [editable]: https://playwright.dev/docs/actionability#editable
+ // [locators]: https://playwright.dev/docs/locators
+ IsEditable() (bool, error)
+
+ // Returns whether the element is [enabled].
+ //
+ // Deprecated: Use locator-based [Locator.IsEnabled] instead. Read more about [locators].
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [locators]: https://playwright.dev/docs/locators
+ IsEnabled() (bool, error)
+
+ // Returns whether the element is hidden, the opposite of [visible].
+ //
+ // Deprecated: Use locator-based [Locator.IsHidden] instead. Read more about [locators].
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [locators]: https://playwright.dev/docs/locators
+ IsHidden() (bool, error)
+
+ // Returns whether the element is [visible].
+ //
+ // Deprecated: Use locator-based [Locator.IsVisible] instead. Read more about [locators].
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [locators]: https://playwright.dev/docs/locators
+ IsVisible() (bool, error)
+
+ // Returns the frame containing the given element.
+ OwnerFrame() (Frame, error)
+
+ // Focuses the element, and then uses [Keyboard.Down] and [Keyboard.Up].
+ // “[object Object]” can specify the intended
+ // [keyboardEvent.Key] value or a single character
+ // to generate the text for. A superset of the “[object Object]” values can be found
+ // [here]. Examples of the keys are:
+ // `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
+ // `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`,
+ // etc.
+ // Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`,
+ // `ControlOrMeta`.
+ // Holding down `Shift` will type the text that corresponds to the “[object Object]” in the upper case.
+ // If “[object Object]” is a single character, it is case-sensitive, so the values `a` and `A` will generate different
+ // respective texts.
+ // Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+T"` are supported as well. When
+ // specified with the modifier, modifier is pressed and being held while the subsequent key is being pressed.
+ //
+ // Deprecated: Use locator-based [Locator.Press] instead. Read more about [locators].
+ //
+ // key: Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
+ //
+ // [keyboardEvent.Key]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
+ // [here]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
+ // [locators]: https://playwright.dev/docs/locators
+ Press(key string, options ...ElementHandlePressOptions) error
+
+ // The method finds an element matching the specified selector in the `ElementHandle`'s subtree. If no elements match
+ // the selector, returns `null`.
+ //
+ // Deprecated: Use locator-based [Page.Locator] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ QuerySelector(selector string) (ElementHandle, error)
+
+ // The method finds all elements matching the specified selector in the `ElementHandle`s subtree. If no elements match
+ // the selector, returns empty array.
+ //
+ // Deprecated: Use locator-based [Page.Locator] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ QuerySelectorAll(selector string) ([]ElementHandle, error)
+
+ // This method captures a screenshot of the page, clipped to the size and position of this particular element. If the
+ // element is covered by other elements, it will not be actually visible on the screenshot. If the element is a
+ // scrollable container, only the currently scrolled content will be visible on the screenshot.
+ // This method waits for the [actionability] checks, then scrolls element into view before taking
+ // a screenshot. If the element is detached from DOM, the method throws an error.
+ // Returns the buffer with the captured screenshot.
+ //
+ // Deprecated: Use locator-based [Locator.Screenshot] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Screenshot(options ...ElementHandleScreenshotOptions) ([]byte, error)
+
+ // This method waits for [actionability] checks, then tries to scroll element into view, unless
+ // it is completely visible as defined by
+ // [IntersectionObserver]'s `ratio`.
+ // Throws when `elementHandle` does not point to an element
+ // [connected] to a Document or a ShadowRoot.
+ // See [scrolling] for alternative ways to scroll.
+ //
+ // Deprecated: Use locator-based [Locator.ScrollIntoViewIfNeeded] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [IntersectionObserver]: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
+ // [connected]: https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected
+ // [scrolling]: https://playwright.dev/docs/input#scrolling
+ // [locators]: https://playwright.dev/docs/locators
+ ScrollIntoViewIfNeeded(options ...ElementHandleScrollIntoViewIfNeededOptions) error
+
+ // This method waits for [actionability] checks, waits until all specified options are present in
+ // the `<select>` element and selects these options.
+ // If the target element is not a `<select>` element, this method throws an error. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], the control will be used
+ // instead.
+ // Returns the array of option values that have been successfully selected.
+ // Triggers a `change` and `input` event once all the provided options have been selected.
+ //
+ // Deprecated: Use locator-based [Locator.SelectOption] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ SelectOption(values SelectOptionValues, options ...ElementHandleSelectOptionOptions) ([]string, error)
+
+ // This method waits for [actionability] checks, then focuses the element and selects all its
+ // text content.
+ // If the element is inside the `<label>` element that has an associated
+ // [control], focuses and selects text in
+ // the control instead.
+ //
+ // Deprecated: Use locator-based [Locator.SelectText] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ SelectText(options ...ElementHandleSelectTextOptions) error
+
+ // This method checks or unchecks an element by performing the following steps:
+ // 1. Ensure that element is a checkbox or a radio input. If not, this method throws.
+ // 2. If the element already has the right checked state, this method returns immediately.
+ // 3. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 4. Scroll the element into view if needed.
+ // 5. Use [Page.Mouse] to click in the center of the element.
+ // 6. Ensure that the element is now checked or unchecked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.SetChecked] instead. Read more about [locators].
+ //
+ // checked: Whether to check or uncheck the checkbox.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ SetChecked(checked bool, options ...ElementHandleSetCheckedOptions) error
+
+ // Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then
+ // they are resolved relative to the current working directory. For empty array, clears the selected files. For inputs
+ // with a `[webkitdirectory]` attribute, only a single directory path is supported.
+ // This method expects [ElementHandle] to point to an
+ // [input element]. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], targets the control instead.
+ //
+ // Deprecated: Use locator-based [Locator.SetInputFiles] instead. Read more about [locators].
+ //
+ // [input element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ SetInputFiles(files interface{}, options ...ElementHandleSetInputFilesOptions) error
+
+ // This method taps the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 2. Scroll the element into view if needed.
+ // 3. Use [Page.Touchscreen] to tap the center of the element, or the specified “[object Object]”.
+ // 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 “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** `elementHandle.tap()` requires that the `hasTouch` option of the browser context be set to true.
+ //
+ // Deprecated: Use locator-based [Locator.Tap] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Tap(options ...ElementHandleTapOptions) error
+
+ // Returns the `node.textContent`.
+ //
+ // Deprecated: Use locator-based [Locator.TextContent] instead. Read more about [locators].
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ TextContent() (string, error)
+
+ // Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the
+ // text.
+ // To press a special key, like `Control` or `ArrowDown`, use [ElementHandle.Press].
+ //
+ // Deprecated: In most cases, you should use [Locator.Fill] instead. You only need to press keys one by one if there is special keyboard handling on the page - in this case use [Locator.PressSequentially].
+ //
+ // text: A text to type into a focused element.
+ Type(text string, options ...ElementHandleTypeOptions) error
+
+ // This method checks the element by performing the following steps:
+ // 1. Ensure that element is a checkbox or a radio input. If not, this method throws. If the element is already
+ // unchecked, this method returns immediately.
+ // 2. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to click in the center of the element.
+ // 5. Ensure that the element is now unchecked. 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 “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Uncheck] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Uncheck(options ...ElementHandleUncheckOptions) error
+
+ // Returns when the element satisfies the “[object Object]”.
+ // Depending on the “[object Object]” parameter, this method waits for one of the [actionability]
+ // checks to pass. This method throws when the element is detached while waiting, unless waiting for the `"hidden"`
+ // state.
+ // - `"visible"` Wait until the element is [visible].
+ // - `"hidden"` Wait until the element is [not visible] or not attached. Note that
+ // waiting for hidden does not throw when the element detaches.
+ // - `"stable"` Wait until the element is both [visible] and
+ // [stable].
+ // - `"enabled"` Wait until the element is [enabled].
+ // - `"disabled"` Wait until the element is [not enabled].
+ // - `"editable"` Wait until the element is [editable].
+ // If the element does not satisfy the condition for the “[object Object]” milliseconds, this method will throw.
+ //
+ // state: A state to wait for, see below for more details.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [not visible]: https://playwright.dev/docs/actionability#visible
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [stable]: https://playwright.dev/docs/actionability#stable
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [not enabled]: https://playwright.dev/docs/actionability#enabled
+ // [editable]: https://playwright.dev/docs/actionability#editable
+ WaitForElementState(state ElementState, options ...ElementHandleWaitForElementStateOptions) error
+
+ // Returns element specified by selector when it satisfies “[object Object]” option. Returns `null` if waiting for
+ // `hidden` or `detached`.
+ // Wait for the “[object Object]” relative to the element handle to satisfy “[object Object]” option (either
+ // appear/disappear from dom, or become visible/hidden). If at the moment of calling the method “[object Object]”
+ // already satisfies the condition, the method will return immediately. If the selector doesn't satisfy the condition
+ // for the “[object Object]” milliseconds, the function will throw.
+ //
+ // Deprecated: Use web assertions that assert visibility or a locator-based [Locator.WaitFor] instead.
+ //
+ // selector: A selector to query for.
+ WaitForSelector(selector string, options ...ElementHandleWaitForSelectorOptions) (ElementHandle, error)
+}
+
+// [FileChooser] objects are dispatched by the page in the [Page.OnFileChooser] event.
+type FileChooser interface {
+ // Returns input element associated with this file chooser.
+ Element() ElementHandle
+
+ // Returns whether this file chooser accepts multiple files.
+ IsMultiple() bool
+
+ // Returns page this file chooser belongs to.
+ Page() Page
+
+ // Sets the value of the file input this chooser is associated with. If some of the `filePaths` are relative paths,
+ // then they are resolved relative to the current working directory. For empty array, clears the selected files.
+ SetFiles(files interface{}, options ...FileChooserSetFilesOptions) error
+}
+
+// At every point of time, page exposes its current frame tree via the [Page.MainFrame] and [Frame.ChildFrames]
+// methods.
+// [Frame] object's lifecycle is controlled by three events, dispatched on the page object:
+// - [Page.OnFrameAttached] - fired when the frame gets attached to the page. A Frame can be attached to the page
+// only once.
+// - [Page.OnFrameNavigated] - fired when the frame commits navigation to a different URL.
+// - [Page.OnFrameDetached] - fired when the frame gets detached from the page. A Frame can be detached from the
+// page only once.
+//
+// An example of dumping frame tree:
+type Frame interface {
+ // Returns the added tag when the script's onload fires or when the script content was injected into frame.
+ // Adds a `<script>` tag into the page with the desired url or content.
+ AddScriptTag(options FrameAddScriptTagOptions) (ElementHandle, error)
+
+ // Returns the added tag when the stylesheet's onload fires or when the CSS content was injected into frame.
+ // Adds a `<link rel="stylesheet">` tag into the page with the desired url or a `<style type="text/css">` tag with the
+ // content.
+ AddStyleTag(options FrameAddStyleTagOptions) (ElementHandle, error)
+
+ // This method checks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Ensure that matched element is a checkbox or a radio input. If not, this method throws. If the element is
+ // already checked, this method returns immediately.
+ // 3. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 4. Scroll the element into view if needed.
+ // 5. Use [Page.Mouse] to click in the center of the element.
+ // 6. Ensure that the element is now checked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Check] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Check(selector string, options ...FrameCheckOptions) error
+
+ ChildFrames() []Frame
+
+ // This method clicks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to click in the center of the element, or the specified “[object Object]”.
+ // 5. Wait for initiated navigations to either succeed or fail, unless “[object Object]” option is set.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Click] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Click(selector string, options ...FrameClickOptions) error
+
+ // Gets the full HTML contents of the frame, including the doctype.
+ Content() (string, error)
+
+ // This method double clicks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to double click in the center of the element, or the specified “[object Object]”. if the
+ // first click of the `dblclick()` triggers a navigation event, this method will throw.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** `frame.dblclick()` dispatches two `click` events and a single `dblclick` event.
+ //
+ // Deprecated: Use locator-based [Locator.Dblclick] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Dblclick(selector string, options ...FrameDblclickOptions) 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. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. typ: DOM event type: `"click"`, `"dragstart"`, etc.
+ // 3. 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
+ // [WheelEvent]: https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/WheelEvent
+ // [locators]: https://playwright.dev/docs/locators
+ DispatchEvent(selector string, typ string, eventInit interface{}, options ...FrameDispatchEventOptions) error
+
+ //
+ // 1. source: A selector to search for an element to drag. If there are multiple elements satisfying the selector, the first will
+ // be used.
+ // 2. target: A selector to search for an element to drop onto. If there are multiple elements satisfying the selector, the first
+ // will be used.
+ DragAndDrop(source string, target string, options ...FrameDragAndDropOptions) error
+
+ // Returns the return value of “[object Object]”.
+ // The method finds an element matching the specified selector within the frame and passes it as a first argument to
+ // “[object Object]”. If no elements match the selector, the method throws an error.
+ // If “[object Object]” returns a [Promise], then [Frame.EvalOnSelector] would wait for the promise to resolve and
+ // return its value.
+ //
+ // Deprecated: This method does not wait for the element to pass the 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.
+ // 3. arg: Optional argument to pass to “[object Object]”.
+ EvalOnSelector(selector string, expression string, arg interface{}, options ...FrameEvalOnSelectorOptions) (interface{}, error)
+
+ // Returns the return value of “[object Object]”.
+ // The method finds all elements matching the specified selector within the frame and passes an array of matched
+ // elements as a first argument to “[object Object]”.
+ // If “[object Object]” returns a [Promise], then [Frame.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.
+ // 3. arg: Optional argument to pass to “[object Object]”.
+ EvalOnSelectorAll(selector string, expression string, arg ...interface{}) (interface{}, error)
+
+ // Returns the return value of “[object Object]”.
+ // If the function passed to the [Frame.Evaluate] returns a [Promise], then [Frame.Evaluate] would wait for the
+ // promise to resolve and return its value.
+ // If the function passed to the [Frame.Evaluate] returns a non-[Serializable] value, then [Frame.Evaluate] returns
+ // `undefined`. Playwright also supports transferring some additional values that are not serializable by `JSON`:
+ // `-0`, `NaN`, `Infinity`, `-Infinity`.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ Evaluate(expression string, arg ...interface{}) (interface{}, error)
+
+ // Returns the return value of “[object Object]” as a [JSHandle].
+ // The only difference between [Frame.Evaluate] and [Frame.EvaluateHandle] is that [Frame.EvaluateHandle] returns
+ // [JSHandle].
+ // If the function, passed to the [Frame.EvaluateHandle], returns a [Promise], then [Frame.EvaluateHandle] would wait
+ // for the promise to resolve and return its value.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ EvaluateHandle(expression string, arg ...interface{}) (JSHandle, error)
+
+ // This method waits for an element matching “[object Object]”, waits for [actionability] checks,
+ // focuses the element, fills it and triggers an `input` event after filling. Note that you can pass an empty string
+ // to clear the input field.
+ // If the target element is not an `<input>`, `<textarea>` or `[contenteditable]` element, this method throws an
+ // error. However, if the element is inside the `<label>` element that has an associated
+ // [control], the control will be filled
+ // instead.
+ // To send fine-grained keyboard events, use [Locator.PressSequentially].
+ //
+ // Deprecated: Use locator-based [Locator.Fill] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. value: Value to fill for the `<input>`, `<textarea>` or `[contenteditable]` element.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ Fill(selector string, value string, options ...FrameFillOptions) error
+
+ // This method fetches an element with “[object Object]” and focuses it. If there's no element matching
+ // “[object Object]”, the method waits until a matching element appears in the DOM.
+ //
+ // Deprecated: Use locator-based [Locator.Focus] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ Focus(selector string, options ...FrameFocusOptions) error
+
+ // Returns the `frame` or `iframe` element handle which corresponds to this frame.
+ // This is an inverse of [ElementHandle.ContentFrame]. Note that returned handle actually belongs to the parent frame.
+ // This method throws an error if the frame has been detached before `frameElement()` returns.
+ FrameElement() (ElementHandle, error)
+
+ // When working with iframes, you can create a frame locator that will enter the iframe and allow selecting elements
+ // in that iframe.
+ //
+ // selector: A selector to use when resolving DOM element.
+ FrameLocator(selector string) FrameLocator
+
+ // Returns element attribute value.
+ //
+ // Deprecated: Use locator-based [Locator.GetAttribute] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. name: Attribute name to get the value for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ GetAttribute(selector string, name string, options ...FrameGetAttributeOptions) (string, error)
+
+ // Allows locating elements by their alt text.
+ //
+ // text: Text to locate the element for.
+ GetByAltText(text interface{}, options ...FrameGetByAltTextOptions) Locator
+
+ // Allows locating input elements by the text of the associated `<label>` or `aria-labelledby` element, or by the
+ // `aria-label` attribute.
+ //
+ // text: Text to locate the element for.
+ GetByLabel(text interface{}, options ...FrameGetByLabelOptions) Locator
+
+ // Allows locating input elements by the placeholder text.
+ //
+ // text: Text to locate the element for.
+ GetByPlaceholder(text interface{}, options ...FrameGetByPlaceholderOptions) Locator
+
+ // Allows locating elements by their [ARIA role],
+ // [ARIA attributes] and
+ // [accessible name].
+ //
+ // # Details
+ //
+ // Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback
+ // about the ARIA guidelines.
+ // Many html elements have an implicitly [defined role]
+ // that is recognized by the role selector. You can find all the
+ // [supported roles here]. ARIA guidelines **do not recommend**
+ // duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
+ //
+ // role: Required aria role.
+ //
+ // [ARIA role]: https://www.w3.org/TR/wai-aria-1.2/#roles
+ // [ARIA attributes]: https://www.w3.org/TR/wai-aria-1.2/#aria-attributes
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [defined role]: https://w3c.github.io/html-aam/#html-element-role-mappings
+ // [supported roles here]: https://www.w3.org/TR/wai-aria-1.2/#role_definitions
+ GetByRole(role AriaRole, options ...FrameGetByRoleOptions) Locator
+
+ // Locate element by the test id.
+ //
+ // # Details
+ //
+ // By default, the `data-testid` attribute is used as a test id. Use [Selectors.SetTestIdAttribute] to configure a
+ // different test id attribute if necessary.
+ //
+ // testId: Id to locate the element by.
+ GetByTestId(testId interface{}) Locator
+
+ // Allows locating elements that contain given text.
+ // See also [Locator.Filter] that allows to match by another criteria, like an accessible role, and then filter by the
+ // text content.
+ //
+ // # Details
+ //
+ // Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into
+ // one, turns line breaks into spaces and ignores leading and trailing whitespace.
+ // Input elements of the type `button` and `submit` are matched by their `value` instead of the text content. For
+ // example, locating by text `"Log in"` matches `<input type=button value="Log in">`.
+ //
+ // text: Text to locate the element for.
+ GetByText(text interface{}, options ...FrameGetByTextOptions) Locator
+
+ // Allows locating elements by their title attribute.
+ //
+ // text: Text to locate the element for.
+ GetByTitle(text interface{}, options ...FrameGetByTitleOptions) Locator
+
+ // Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of
+ // the last redirect.
+ // The method will throw an error if:
+ // - there's an SSL error (e.g. in case of self-signed certificates).
+ // - target URL is invalid.
+ // - the “[object Object]” is exceeded during navigation.
+ // - the remote server does not respond or is unreachable.
+ // - the main resource failed to load.
+ // The method will not throw an error when any valid HTTP status code is returned by the remote server, including 404
+ // "Not Found" and 500 "Internal Server Error". The status code for such responses can be retrieved by calling
+ // [Response.Status].
+ // **NOTE** The method either throws an error or returns a main resource response. The only exceptions are navigation
+ // to `about:blank` or navigation to the same URL with a different hash, which would succeed and return `null`.
+ // **NOTE** Headless mode doesn't support navigation to a PDF document. See the
+ // [upstream issue].
+ //
+ // url: URL to navigate frame to. The url should include scheme, e.g. `https://`.
+ //
+ // [upstream issue]: https://bugs.chromium.org/p/chromium/issues/detail?id=761295
+ Goto(url string, options ...FrameGotoOptions) (Response, error)
+
+ // This method hovers over an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to hover over the center of the element, or the specified “[object Object]”.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Hover] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Hover(selector string, options ...FrameHoverOptions) error
+
+ // Returns `element.innerHTML`.
+ //
+ // Deprecated: Use locator-based [Locator.InnerHTML] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ InnerHTML(selector string, options ...FrameInnerHTMLOptions) (string, error)
+
+ // Returns `element.innerText`.
+ //
+ // Deprecated: Use locator-based [Locator.InnerText] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ InnerText(selector string, options ...FrameInnerTextOptions) (string, error)
+
+ // Returns `input.value` for the selected `<input>` or `<textarea>` or `<select>` element.
+ // Throws for non-input elements. However, if the element is inside the `<label>` element that has an associated
+ // [control], returns the value of the
+ // control.
+ //
+ // Deprecated: Use locator-based [Locator.InputValue] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ InputValue(selector string, options ...FrameInputValueOptions) (string, error)
+
+ // Returns whether the element is checked. Throws if the element is not a checkbox or radio input.
+ //
+ // Deprecated: Use locator-based [Locator.IsChecked] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ IsChecked(selector string, options ...FrameIsCheckedOptions) (bool, error)
+
+ // Returns `true` if the frame has been detached, or `false` otherwise.
+ IsDetached() bool
+
+ // Returns whether the element is disabled, the opposite of [enabled].
+ //
+ // Deprecated: Use locator-based [Locator.IsDisabled] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [locators]: https://playwright.dev/docs/locators
+ IsDisabled(selector string, options ...FrameIsDisabledOptions) (bool, error)
+
+ // Returns whether the element is [editable].
+ //
+ // Deprecated: Use locator-based [Locator.IsEditable] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [editable]: https://playwright.dev/docs/actionability#editable
+ // [locators]: https://playwright.dev/docs/locators
+ IsEditable(selector string, options ...FrameIsEditableOptions) (bool, error)
+
+ // Returns whether the element is [enabled].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ IsEnabled(selector string, options ...FrameIsEnabledOptions) (bool, error)
+
+ // Returns whether the element is hidden, the opposite of [visible]. “[object Object]”
+ // that does not match any elements is considered hidden.
+ //
+ // Deprecated: Use locator-based [Locator.IsHidden] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [locators]: https://playwright.dev/docs/locators
+ IsHidden(selector string, options ...FrameIsHiddenOptions) (bool, error)
+
+ // Returns whether the element is [visible]. “[object Object]” that does not match any
+ // elements is considered not visible.
+ //
+ // Deprecated: Use locator-based [Locator.IsVisible] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [locators]: https://playwright.dev/docs/locators
+ IsVisible(selector string, options ...FrameIsVisibleOptions) (bool, error)
+
+ // The method returns an element locator that can be used to perform actions on this page / frame. Locator is resolved
+ // to the element immediately before performing an action, so a series of actions on the same locator can in fact be
+ // performed on different DOM elements. That would happen if the DOM structure between those actions has changed.
+ // [Learn more about locators].
+ // [Learn more about locators].
+ //
+ // selector: A selector to use when resolving DOM element.
+ //
+ // [Learn more about locators]: https://playwright.dev/docs/locators
+ // [Learn more about locators]: https://playwright.dev/docs/locators
+ Locator(selector string, options ...FrameLocatorOptions) Locator
+
+ // Returns frame's name attribute as specified in the tag.
+ // If the name is empty, returns the id attribute instead.
+ // **NOTE** This value is calculated once when the frame is created, and will not update if the attribute is changed
+ // later.
+ Name() string
+
+ // Returns the page containing this frame.
+ Page() Page
+
+ // Parent frame, if any. Detached frames and main frames return `null`.
+ ParentFrame() Frame
+
+ // “[object Object]” can specify the intended
+ // [keyboardEvent.Key] value or a single character
+ // to generate the text for. A superset of the “[object Object]” values can be found
+ // [here]. Examples of the keys are:
+ // `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
+ // `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`,
+ // etc.
+ // Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`,
+ // `ControlOrMeta`. `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
+ // Holding down `Shift` will type the text that corresponds to the “[object Object]” in the upper case.
+ // If “[object Object]” is a single character, it is case-sensitive, so the values `a` and `A` will generate different
+ // respective texts.
+ // Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+T"` are supported as well. When
+ // specified with the modifier, modifier is pressed and being held while the subsequent key is being pressed.
+ //
+ // Deprecated: Use locator-based [Locator.Press] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. key: Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
+ //
+ // [keyboardEvent.Key]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
+ // [here]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
+ // [locators]: https://playwright.dev/docs/locators
+ Press(selector string, key string, options ...FramePressOptions) error
+
+ // Returns the ElementHandle pointing to the frame element.
+ // **NOTE** The use of [ElementHandle] is discouraged, use [Locator] objects and web-first assertions instead.
+ // The method finds an element matching the specified selector within the frame. If no elements match the selector,
+ // returns `null`.
+ //
+ // Deprecated: Use locator-based [Frame.Locator] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ QuerySelector(selector string, options ...FrameQuerySelectorOptions) (ElementHandle, error)
+
+ // Returns the ElementHandles pointing to the frame elements.
+ // **NOTE** The use of [ElementHandle] is discouraged, use [Locator] objects instead.
+ // The method finds all elements matching the specified selector within the frame. If no elements match the selector,
+ // returns empty array.
+ //
+ // Deprecated: Use locator-based [Frame.Locator] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ QuerySelectorAll(selector string) ([]ElementHandle, error)
+
+ // This method waits for an element matching “[object Object]”, waits for [actionability] checks,
+ // waits until all specified options are present in the `<select>` element and selects these options.
+ // If the target element is not a `<select>` element, this method throws an error. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], the control will be used
+ // instead.
+ // Returns the array of option values that have been successfully selected.
+ // Triggers a `change` and `input` event once all the provided options have been selected.
+ //
+ // Deprecated: Use locator-based [Locator.SelectOption] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ SelectOption(selector string, values SelectOptionValues, options ...FrameSelectOptionOptions) ([]string, error)
+
+ // This method checks or unchecks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Ensure that matched element is a checkbox or a radio input. If not, this method throws.
+ // 3. If the element already has the right checked state, this method returns immediately.
+ // 4. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 5. Scroll the element into view if needed.
+ // 6. Use [Page.Mouse] to click in the center of the element.
+ // 7. Ensure that the element is now checked or unchecked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.SetChecked] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. checked: Whether to check or uncheck the checkbox.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ SetChecked(selector string, checked bool, options ...FrameSetCheckedOptions) error
+
+ // This method internally calls [document.Write()],
+ // inheriting all its specific characteristics and behaviors.
+ //
+ // html: HTML markup to assign to the page.
+ //
+ // [document.Write()]: https://developer.mozilla.org/en-US/docs/Web/API/Document/write
+ SetContent(html string, options ...FrameSetContentOptions) error
+
+ // Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then
+ // they are resolved relative to the current working directory. For empty array, clears the selected files.
+ // This method expects “[object Object]” to point to an
+ // [input element]. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], targets the control instead.
+ //
+ // Deprecated: Use locator-based [Locator.SetInputFiles] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [input element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ SetInputFiles(selector string, files interface{}, options ...FrameSetInputFilesOptions) error
+
+ // This method taps an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Touchscreen] to tap the center of the element, or the specified “[object Object]”.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** `frame.tap()` requires that the `hasTouch` option of the browser context be set to true.
+ //
+ // Deprecated: Use locator-based [Locator.Tap] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Tap(selector string, options ...FrameTapOptions) error
+
+ // Returns `element.textContent`.
+ //
+ // Deprecated: Use locator-based [Locator.TextContent] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ TextContent(selector string, options ...FrameTextContentOptions) (string, error)
+
+ // Returns the page title.
+ Title() (string, error)
+
+ // Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text. `frame.type` can be used
+ // to send fine-grained keyboard events. To fill values in form fields, use [Frame.Fill].
+ // To press a special key, like `Control` or `ArrowDown`, use [Keyboard.Press].
+ //
+ // Deprecated: In most cases, you should use [Locator.Fill] instead. You only need to press keys one by one if there is special keyboard handling on the page - in this case use [Locator.PressSequentially].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. text: A text to type into a focused element.
+ Type(selector string, text string, options ...FrameTypeOptions) error
+
+ // This method checks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Ensure that matched element is a checkbox or a radio input. If not, this method throws. If the element is
+ // already unchecked, this method returns immediately.
+ // 3. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 4. Scroll the element into view if needed.
+ // 5. Use [Page.Mouse] to click in the center of the element.
+ // 6. Ensure that the element is now unchecked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Uncheck] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Uncheck(selector string, options ...FrameUncheckOptions) error
+
+ // Returns frame's url.
+ URL() string
+
+ // Returns when the “[object Object]” returns a truthy value, returns that value.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ WaitForFunction(expression string, arg interface{}, options ...FrameWaitForFunctionOptions) (JSHandle, error)
+
+ // Waits for the required load state to be reached.
+ // This returns when the frame reaches a required load state, `load` by default. The navigation must have been
+ // committed when this method is called. If current document has already reached the required state, resolves
+ // immediately.
+ // **NOTE** Most of the time, this method is not needed because Playwright
+ // [auto-waits before every action].
+ //
+ // [auto-waits before every action]: https://playwright.dev/docs/actionability
+ WaitForLoadState(options ...FrameWaitForLoadStateOptions) error
+
+ // Waits for the frame navigation and returns the main resource response. In case of multiple redirects, the
+ // navigation will resolve with the response of the last redirect. In case of navigation to a different anchor or
+ // navigation due to History API usage, the navigation will resolve with `null`.
+ //
+ // Deprecated: This method is inherently racy, please use [Frame.WaitForURL] instead.
+ //
+ // [History API]: https://developer.mozilla.org/en-US/docs/Web/API/History_API
+ ExpectNavigation(cb func() error, options ...FrameExpectNavigationOptions) (Response, error)
+
+ // Returns when element specified by selector satisfies “[object Object]” option. Returns `null` if waiting for
+ // `hidden` or `detached`.
+ // **NOTE** Playwright automatically waits for element to be ready before performing an action. Using [Locator]
+ // objects and web-first assertions make the code wait-for-selector-free.
+ // Wait for the “[object Object]” to satisfy “[object Object]” option (either appear/disappear from dom, or become
+ // visible/hidden). If at the moment of calling the method “[object Object]” already satisfies the condition, the
+ // method will return immediately. If the selector doesn't satisfy the condition for the “[object Object]”
+ // milliseconds, the function will throw.
+ //
+ // Deprecated: Use web assertions that assert visibility or a locator-based [Locator.WaitFor] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ WaitForSelector(selector string, options ...FrameWaitForSelectorOptions) (ElementHandle, error)
+
+ // Waits for the given “[object Object]” in milliseconds.
+ // Note that `frame.waitForTimeout()` should only be used for debugging. Tests using the timer in production are going
+ // to be flaky. Use signals such as network events, selectors becoming visible and others instead.
+ //
+ // Deprecated: Never wait for timeout in production. Tests that wait for time are inherently flaky. Use [Locator] actions and web assertions that wait automatically.
+ //
+ // timeout: A timeout to wait for
+ WaitForTimeout(timeout float64)
+
+ // Waits for the frame to navigate to the given URL.
+ //
+ // url: A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if
+ // the parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly
+ // equal to the string.
+ WaitForURL(url interface{}, options ...FrameWaitForURLOptions) error
+}
+
+// FrameLocator represents a view to the `iframe` on the page. It captures the logic sufficient to retrieve the
+// `iframe` and locate elements in that iframe. FrameLocator can be created with either [Locator.ContentFrame],
+// [Page.FrameLocator] or [Locator.FrameLocator] method.
+// **Strictness**
+// Frame locators are strict. This means that all operations on frame locators will throw if more than one element
+// matches a given selector.
+// **Converting Locator to FrameLocator**
+// If you have a [Locator] object pointing to an `iframe` it can be converted to [FrameLocator] using
+// [Locator.ContentFrame].
+// **Converting FrameLocator to Locator**
+// If you have a [FrameLocator] object it can be converted to [Locator] pointing to the same `iframe` using
+// [FrameLocator.Owner].
+type FrameLocator interface {
+ // Returns locator to the first matching frame.
+ //
+ // Deprecated: Use [Locator.First] followed by [Locator.ContentFrame] instead.
+ First() FrameLocator
+
+ // When working with iframes, you can create a frame locator that will enter the iframe and allow selecting elements
+ // in that iframe.
+ //
+ // selector: A selector to use when resolving DOM element.
+ FrameLocator(selector string) FrameLocator
+
+ // Allows locating elements by their alt text.
+ //
+ // text: Text to locate the element for.
+ GetByAltText(text interface{}, options ...FrameLocatorGetByAltTextOptions) Locator
+
+ // Allows locating input elements by the text of the associated `<label>` or `aria-labelledby` element, or by the
+ // `aria-label` attribute.
+ //
+ // text: Text to locate the element for.
+ GetByLabel(text interface{}, options ...FrameLocatorGetByLabelOptions) Locator
+
+ // Allows locating input elements by the placeholder text.
+ //
+ // text: Text to locate the element for.
+ GetByPlaceholder(text interface{}, options ...FrameLocatorGetByPlaceholderOptions) Locator
+
+ // Allows locating elements by their [ARIA role],
+ // [ARIA attributes] and
+ // [accessible name].
+ //
+ // # Details
+ //
+ // Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback
+ // about the ARIA guidelines.
+ // Many html elements have an implicitly [defined role]
+ // that is recognized by the role selector. You can find all the
+ // [supported roles here]. ARIA guidelines **do not recommend**
+ // duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
+ //
+ // role: Required aria role.
+ //
+ // [ARIA role]: https://www.w3.org/TR/wai-aria-1.2/#roles
+ // [ARIA attributes]: https://www.w3.org/TR/wai-aria-1.2/#aria-attributes
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [defined role]: https://w3c.github.io/html-aam/#html-element-role-mappings
+ // [supported roles here]: https://www.w3.org/TR/wai-aria-1.2/#role_definitions
+ GetByRole(role AriaRole, options ...FrameLocatorGetByRoleOptions) Locator
+
+ // Locate element by the test id.
+ //
+ // # Details
+ //
+ // By default, the `data-testid` attribute is used as a test id. Use [Selectors.SetTestIdAttribute] to configure a
+ // different test id attribute if necessary.
+ //
+ // testId: Id to locate the element by.
+ GetByTestId(testId interface{}) Locator
+
+ // Allows locating elements that contain given text.
+ // See also [Locator.Filter] that allows to match by another criteria, like an accessible role, and then filter by the
+ // text content.
+ //
+ // # Details
+ //
+ // Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into
+ // one, turns line breaks into spaces and ignores leading and trailing whitespace.
+ // Input elements of the type `button` and `submit` are matched by their `value` instead of the text content. For
+ // example, locating by text `"Log in"` matches `<input type=button value="Log in">`.
+ //
+ // text: Text to locate the element for.
+ GetByText(text interface{}, options ...FrameLocatorGetByTextOptions) Locator
+
+ // Allows locating elements by their title attribute.
+ //
+ // text: Text to locate the element for.
+ GetByTitle(text interface{}, options ...FrameLocatorGetByTitleOptions) Locator
+
+ // Returns locator to the last matching frame.
+ //
+ // Deprecated: Use [Locator.Last] followed by [Locator.ContentFrame] instead.
+ Last() FrameLocator
+
+ // The method finds an element matching the specified selector in the locator's subtree. It also accepts filter
+ // options, similar to [Locator.Filter] method.
+ // [Learn more about locators].
+ //
+ // selectorOrLocator: A selector or locator to use when resolving DOM element.
+ //
+ // [Learn more about locators]: https://playwright.dev/docs/locators
+ Locator(selectorOrLocator interface{}, options ...FrameLocatorLocatorOptions) Locator
+
+ // Returns locator to the n-th matching frame. It's zero based, `nth(0)` selects the first frame.
+ //
+ // Deprecated: Use [Locator.Nth] followed by [Locator.ContentFrame] instead.
+ Nth(index int) FrameLocator
+
+ // Returns a [Locator] object pointing to the same `iframe` as this frame locator.
+ // Useful when you have a [FrameLocator] object obtained somewhere, and later on would like to interact with the
+ // `iframe` element.
+ // For a reverse operation, use [Locator.ContentFrame].
+ Owner() Locator
+}
+
+// JSHandle represents an in-page JavaScript object. JSHandles can be created with the [Page.EvaluateHandle] method.
+// JSHandle prevents the referenced JavaScript object being garbage collected unless the handle is exposed with
+// [JSHandle.Dispose]. JSHandles are auto-disposed when their origin frame gets navigated or the parent context gets
+// destroyed.
+// JSHandle instances can be used as an argument in [Page.EvalOnSelector], [Page.Evaluate] and [Page.EvaluateHandle]
+// methods.
+type JSHandle interface {
+ // Returns either `null` or the object handle itself, if the object handle is an instance of [ElementHandle].
+ AsElement() ElementHandle
+
+ // The `jsHandle.dispose` method stops referencing the element handle.
+ Dispose() error
+
+ // Returns the return value of “[object Object]”.
+ // This method passes this handle as the first argument to “[object Object]”.
+ // If “[object Object]” returns a [Promise], then `handle.evaluate` would wait for the promise to resolve and return
+ // its value.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ Evaluate(expression string, arg ...interface{}) (interface{}, error)
+
+ // Returns the return value of “[object Object]” as a [JSHandle].
+ // This method passes this handle as the first argument to “[object Object]”.
+ // The only difference between `jsHandle.evaluate` and `jsHandle.evaluateHandle` is that `jsHandle.evaluateHandle`
+ // returns [JSHandle].
+ // If the function passed to the `jsHandle.evaluateHandle` returns a [Promise], then `jsHandle.evaluateHandle` would
+ // wait for the promise to resolve and return its value.
+ // See [Page.EvaluateHandle] for more details.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ EvaluateHandle(expression string, arg ...interface{}) (JSHandle, error)
+
+ // The method returns a map with **own property names** as keys and JSHandle instances for the property values.
+ GetProperties() (map[string]JSHandle, error)
+
+ // Fetches a single property from the referenced object.
+ //
+ // propertyName: property to get
+ GetProperty(propertyName string) (JSHandle, error)
+
+ // Returns a JSON representation of the object. If the object has a `toJSON` function, it **will not be called**.
+ // **NOTE** The method will return an empty JSON object if the referenced object is not stringifiable. It will throw
+ // an error if the object has circular references.
+ JSONValue() (interface{}, error)
+
+ String() string
+}
+
+// Keyboard provides an api for managing a virtual keyboard. The high level api is [Keyboard.Type], which takes raw
+// characters and generates proper `keydown`, `keypress`/`input`, and `keyup` events on your page.
+// For finer control, you can use [Keyboard.Down], [Keyboard.Up], and [Keyboard.InsertText] to manually fire events as
+// if they were generated from a real keyboard.
+// An example of holding down `Shift` in order to select and delete some text:
+// An example of pressing uppercase `A`
+// An example to trigger select-all with the keyboard
+type Keyboard interface {
+ // Dispatches a `keydown` event.
+ // “[object Object]” can specify the intended
+ // [keyboardEvent.Key] value or a single character
+ // to generate the text for. A superset of the “[object Object]” values can be found
+ // [here]. Examples of the keys are:
+ // `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
+ // `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`,
+ // etc.
+ // Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`,
+ // `ControlOrMeta`. `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
+ // Holding down `Shift` will type the text that corresponds to the “[object Object]” in the upper case.
+ // If “[object Object]” is a single character, it is case-sensitive, so the values `a` and `A` will generate different
+ // respective texts.
+ // If “[object Object]” is a modifier key, `Shift`, `Meta`, `Control`, or `Alt`, subsequent key presses will be sent
+ // with that modifier active. To release the modifier key, use [Keyboard.Up].
+ // After the key is pressed once, subsequent calls to [Keyboard.Down] will have
+ // [repeat] set to true. To release the key,
+ // use [Keyboard.Up].
+ // **NOTE** Modifier keys DO influence `keyboard.down`. Holding down `Shift` will type the text in upper case.
+ //
+ // key: Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
+ //
+ // [keyboardEvent.Key]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
+ // [here]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
+ // [repeat]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat
+ Down(key string) error
+
+ // Dispatches only `input` event, does not emit the `keydown`, `keyup` or `keypress` events.
+ //
+ // text: Sets input to the specified text value.
+ InsertText(text string) error
+
+ // **NOTE** In most cases, you should use [Locator.Press] instead.
+ // “[object Object]” can specify the intended
+ // [keyboardEvent.Key] value or a single character
+ // to generate the text for. A superset of the “[object Object]” values can be found
+ // [here]. Examples of the keys are:
+ // `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
+ // `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`,
+ // etc.
+ // Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`,
+ // `ControlOrMeta`. `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
+ // Holding down `Shift` will type the text that corresponds to the “[object Object]” in the upper case.
+ // If “[object Object]” is a single character, it is case-sensitive, so the values `a` and `A` will generate different
+ // respective texts.
+ // Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+T"` are supported as well. When
+ // specified with the modifier, modifier is pressed and being held while the subsequent key is being pressed.
+ //
+ // key: Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
+ //
+ // [keyboardEvent.Key]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
+ // [here]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
+ Press(key string, options ...KeyboardPressOptions) error
+
+ // **NOTE** In most cases, you should use [Locator.Fill] instead. You only need to press keys one by one if there is
+ // special keyboard handling on the page - in this case use [Locator.PressSequentially].
+ // Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text.
+ // To press a special key, like `Control` or `ArrowDown`, use [Keyboard.Press].
+ //
+ // text: A text to type into a focused element.
+ Type(text string, options ...KeyboardTypeOptions) error
+
+ // Dispatches a `keyup` event.
+ //
+ // key: Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
+ Up(key string) error
+}
+
+// Locators are the central piece of Playwright's auto-waiting and retry-ability. In a nutshell, locators represent a
+// way to find element(s) on the page at any moment. A locator can be created with the [Page.Locator] method.
+// [Learn more about locators].
+//
+// [Learn more about locators]: https://playwright.dev/docs/locators
+type Locator interface {
+ // When the locator points to a list of elements, this returns an array of locators, pointing to their respective
+ // elements.
+ // **NOTE** [Locator.All] does not wait for elements to match the locator, and instead immediately returns whatever is
+ // present in the page.
+ // When the list of elements changes dynamically, [Locator.All] will produce unpredictable and flaky results.
+ // When the list of elements is stable, but loaded dynamically, wait for the full list to finish loading before
+ // calling [Locator.All].
+ All() ([]Locator, error)
+
+ // Returns an array of `node.innerText` values for all matching nodes.
+ // **NOTE** If you need to assert text on the page, prefer [LocatorAssertions.ToHaveText] with “[object Object]”
+ // option to avoid flakiness. See [assertions guide] for more details.
+ //
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ AllInnerTexts() ([]string, error)
+
+ // Returns an array of `node.textContent` values for all matching nodes.
+ // **NOTE** If you need to assert text on the page, prefer [LocatorAssertions.ToHaveText] to avoid flakiness. See
+ // [assertions guide] for more details.
+ //
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ AllTextContents() ([]string, error)
+
+ // Creates a locator that matches both this locator and the argument locator.
+ //
+ // locator: Additional locator to match.
+ And(locator Locator) Locator
+
+ // Captures the aria snapshot of the given element. Read more about [aria snapshots] and
+ // [LocatorAssertions.ToMatchAriaSnapshot] for the corresponding assertion.
+ //
+ // # Details
+ //
+ // This method captures the aria snapshot of the given element. The snapshot is a string that represents the state of
+ // the element and its children. The snapshot can be used to assert the state of the element in the test, or to
+ // compare it to state in the future.
+ // The ARIA snapshot is represented using [YAML] markup language:
+ // - The keys of the objects are the roles and optional accessible names of the elements.
+ // - The values are either text content or an array of child elements.
+ // - Generic static text can be represented with the `text` key.
+ // Below is the HTML markup and the respective ARIA snapshot:
+ // ```html
+ // <ul aria-label="Links">
+ // <li><a href="/">Home</a></li>
+ // <li><a href="/about">About</a></li>
+ // <ul>
+ // ```
+ // ```yml
+ // - list "Links":
+ // - listitem:
+ // - link "Home"
+ // - listitem:
+ // - link "About"
+ // ```
+ //
+ // [aria snapshots]: https://playwright.dev/docs/aria-snapshots
+ // [YAML]: https://yaml.org/spec/1.2.2/
+ AriaSnapshot(options ...LocatorAriaSnapshotOptions) (string, error)
+
+ // Calls [blur] on the element.
+ //
+ // [blur]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur
+ Blur(options ...LocatorBlurOptions) error
+
+ // This method returns the bounding box of the element matching the locator, or `null` if the element is not visible.
+ // The bounding box is calculated relative to the main frame viewport - which is usually the same as the browser
+ // window.
+ //
+ // # Details
+ //
+ // Scrolling affects the returned bounding box, similarly to
+ // [Element.GetBoundingClientRect].
+ // That means `x` and/or `y` may be negative.
+ // Elements from child frames return the bounding box relative to the main frame, unlike the
+ // [Element.GetBoundingClientRect].
+ // Assuming the page is static, it is safe to use bounding box coordinates to perform input. For example, the
+ // following snippet should click the center of the element.
+ //
+ // [Element.GetBoundingClientRect]: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
+ // [Element.GetBoundingClientRect]: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
+ BoundingBox(options ...LocatorBoundingBoxOptions) (*Rect, error)
+
+ // Ensure that checkbox or radio element is checked.
+ //
+ // # Details
+ //
+ // Performs the following steps:
+ // 1. Ensure that element is a checkbox or a radio input. If not, this method throws. If the element is already
+ // checked, this method returns immediately.
+ // 2. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to click in the center of the element.
+ // 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 “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Check(options ...LocatorCheckOptions) error
+
+ // Clear the input field.
+ //
+ // # Details
+ //
+ // This method waits for [actionability] checks, focuses the element, clears it and triggers an
+ // `input` event after clearing.
+ // If the target element is not an `<input>`, `<textarea>` or `[contenteditable]` element, this method throws an
+ // error. However, if the element is inside the `<label>` element that has an associated
+ // [control], the control will be cleared
+ // instead.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ Clear(options ...LocatorClearOptions) error
+
+ // Click an element.
+ //
+ // # Details
+ //
+ // This method clicks the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 2. Scroll the element into view if needed.
+ // 3. Use [Page.Mouse] to click in the center of the element, or the specified “[object Object]”.
+ // 4. Wait for initiated navigations to either succeed or fail, unless “[object Object]” option is set.
+ // 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 “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Click(options ...LocatorClickOptions) error
+
+ // Returns the number of elements matching the locator.
+ // **NOTE** If you need to assert the number of elements on the page, prefer [LocatorAssertions.ToHaveCount] to avoid
+ // flakiness. See [assertions guide] for more details.
+ //
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ Count() (int, error)
+
+ // Double-click an element.
+ //
+ // # Details
+ //
+ // This method double clicks the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” 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 “[object Object]”.
+ // 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 “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** `element.dblclick()` dispatches two `click` events and a single `dblclick` event.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Dblclick(options ...LocatorDblclickOptions) error
+
+ // Programmatically dispatch an event on the matching element.
+ //
+ // # Details
+ //
+ // The snippet above 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()].
+ // Under the hood, it creates an instance of an event based on the given “[object Object]”, initializes it with
+ // “[object Object]” properties and dispatches it on the element. Events are `composed`, `cancelable` and bubble by
+ // default.
+ // Since “[object Object]” is event-specific, please refer to the events documentation for the lists of initial
+ // properties:
+ // - [DeviceMotionEvent]
+ // - [DeviceOrientationEvent]
+ // - [DragEvent]
+ // - [Event]
+ // - [FocusEvent]
+ // - [KeyboardEvent]
+ // - [MouseEvent]
+ // - [PointerEvent]
+ // - [TouchEvent]
+ // - [WheelEvent]
+ // You can also specify [JSHandle] as the property value if you want live objects to be passed into the event:
+ //
+ // 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
+ // [WheelEvent]: https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/WheelEvent
+ DispatchEvent(typ string, eventInit interface{}, options ...LocatorDispatchEventOptions) error
+
+ // Drag the source element towards the target element and drop it.
+ //
+ // # Details
+ //
+ // This method drags the locator to another target locator or target position. It will first move to the source
+ // element, perform a `mousedown`, then move to the target element or position and perform a `mouseup`.
+ //
+ // target: Locator of the element to drag to.
+ DragTo(target Locator, options ...LocatorDragToOptions) error
+
+ // Resolves given locator to the first matching DOM element. If there are no matching elements, waits for one. If
+ // multiple elements match the locator, throws.
+ //
+ // Deprecated: Always prefer using [Locator]s and web assertions over [ElementHandle]s because latter are inherently racy.
+ ElementHandle(options ...LocatorElementHandleOptions) (ElementHandle, error)
+
+ // Resolves given locator to all matching DOM elements. If there are no matching elements, returns an empty list.
+ //
+ // Deprecated: Always prefer using [Locator]s and web assertions over [ElementHandle]s because latter are inherently racy.
+ ElementHandles() ([]ElementHandle, error)
+
+ // Returns a [FrameLocator] object pointing to the same `iframe` as this locator.
+ // Useful when you have a [Locator] object obtained somewhere, and later on would like to interact with the content
+ // inside the frame.
+ // For a reverse operation, use [FrameLocator.Owner].
+ ContentFrame() FrameLocator
+
+ // Execute JavaScript code in the page, taking the matching element as an argument.
+ //
+ // # Details
+ //
+ // Returns the return value of “[object Object]”, called with the matching element as a first argument, and
+ // “[object Object]” as a second argument.
+ // If “[object Object]” returns a [Promise], this method will wait for the promise to resolve and return its value.
+ // If “[object Object]” throws or rejects, this method throws.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ Evaluate(expression string, arg interface{}, options ...LocatorEvaluateOptions) (interface{}, error)
+
+ // Execute JavaScript code in the page, taking all matching elements as an argument.
+ //
+ // # Details
+ //
+ // Returns the return value of “[object Object]”, called with an array of all matching elements as a first argument,
+ // and “[object Object]” as a second argument.
+ // If “[object Object]” returns a [Promise], this method will wait for the promise to resolve and return its value.
+ // If “[object Object]” throws or rejects, this method throws.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ EvaluateAll(expression string, arg ...interface{}) (interface{}, error)
+
+ // Execute JavaScript code in the page, taking the matching element as an argument, and return a [JSHandle] with the
+ // result.
+ //
+ // # Details
+ //
+ // Returns the return value of “[object Object]” as a[JSHandle], called with the matching element as a first argument,
+ // and “[object Object]” as a second argument.
+ // The only difference between [Locator.Evaluate] and [Locator.EvaluateHandle] is that [Locator.EvaluateHandle]
+ // returns [JSHandle].
+ // If “[object Object]” returns a [Promise], this method will wait for the promise to resolve and return its value.
+ // If “[object Object]” throws or rejects, this method throws.
+ // See [Page.EvaluateHandle] for more details.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ EvaluateHandle(expression string, arg interface{}, options ...LocatorEvaluateHandleOptions) (JSHandle, error)
+
+ // Set a value to the input field.
+ //
+ // # Details
+ //
+ // This method waits for [actionability] checks, focuses the element, fills it and triggers an
+ // `input` event after filling. Note that you can pass an empty string to clear the input field.
+ // If the target element is not an `<input>`, `<textarea>` or `[contenteditable]` element, this method throws an
+ // error. However, if the element is inside the `<label>` element that has an associated
+ // [control], the control will be filled
+ // instead.
+ // To send fine-grained keyboard events, use [Locator.PressSequentially].
+ //
+ // value: Value to set for the `<input>`, `<textarea>` or `[contenteditable]` element.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ Fill(value string, options ...LocatorFillOptions) error
+
+ // This method narrows existing locator according to the options, for example filters by text. It can be chained to
+ // filter multiple times.
+ Filter(options ...LocatorFilterOptions) Locator
+
+ // Returns locator to the first matching element.
+ First() Locator
+
+ // Calls [focus] on the matching element.
+ //
+ // [focus]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
+ Focus(options ...LocatorFocusOptions) error
+
+ // When working with iframes, you can create a frame locator that will enter the iframe and allow locating elements in
+ // that iframe:
+ //
+ // selector: A selector to use when resolving DOM element.
+ FrameLocator(selector string) FrameLocator
+
+ // Returns the matching element's attribute value.
+ // **NOTE** If you need to assert an element's attribute, prefer [LocatorAssertions.ToHaveAttribute] to avoid
+ // flakiness. See [assertions guide] for more details.
+ //
+ // name: Attribute name to get the value for.
+ //
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ GetAttribute(name string, options ...LocatorGetAttributeOptions) (string, error)
+
+ // Allows locating elements by their alt text.
+ //
+ // text: Text to locate the element for.
+ GetByAltText(text interface{}, options ...LocatorGetByAltTextOptions) Locator
+
+ // Allows locating input elements by the text of the associated `<label>` or `aria-labelledby` element, or by the
+ // `aria-label` attribute.
+ //
+ // text: Text to locate the element for.
+ GetByLabel(text interface{}, options ...LocatorGetByLabelOptions) Locator
+
+ // Allows locating input elements by the placeholder text.
+ //
+ // text: Text to locate the element for.
+ GetByPlaceholder(text interface{}, options ...LocatorGetByPlaceholderOptions) Locator
+
+ // Allows locating elements by their [ARIA role],
+ // [ARIA attributes] and
+ // [accessible name].
+ //
+ // # Details
+ //
+ // Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback
+ // about the ARIA guidelines.
+ // Many html elements have an implicitly [defined role]
+ // that is recognized by the role selector. You can find all the
+ // [supported roles here]. ARIA guidelines **do not recommend**
+ // duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
+ //
+ // role: Required aria role.
+ //
+ // [ARIA role]: https://www.w3.org/TR/wai-aria-1.2/#roles
+ // [ARIA attributes]: https://www.w3.org/TR/wai-aria-1.2/#aria-attributes
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [defined role]: https://w3c.github.io/html-aam/#html-element-role-mappings
+ // [supported roles here]: https://www.w3.org/TR/wai-aria-1.2/#role_definitions
+ GetByRole(role AriaRole, options ...LocatorGetByRoleOptions) Locator
+
+ // Locate element by the test id.
+ //
+ // # Details
+ //
+ // By default, the `data-testid` attribute is used as a test id. Use [Selectors.SetTestIdAttribute] to configure a
+ // different test id attribute if necessary.
+ //
+ // testId: Id to locate the element by.
+ GetByTestId(testId interface{}) Locator
+
+ // Allows locating elements that contain given text.
+ // See also [Locator.Filter] that allows to match by another criteria, like an accessible role, and then filter by the
+ // text content.
+ //
+ // # Details
+ //
+ // Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into
+ // one, turns line breaks into spaces and ignores leading and trailing whitespace.
+ // Input elements of the type `button` and `submit` are matched by their `value` instead of the text content. For
+ // example, locating by text `"Log in"` matches `<input type=button value="Log in">`.
+ //
+ // text: Text to locate the element for.
+ GetByText(text interface{}, options ...LocatorGetByTextOptions) Locator
+
+ // Allows locating elements by their title attribute.
+ //
+ // text: Text to locate the element for.
+ GetByTitle(text interface{}, options ...LocatorGetByTitleOptions) Locator
+
+ // Highlight the corresponding element(s) on the screen. Useful for debugging, don't commit the code that uses
+ // [Locator.Highlight].
+ Highlight() error
+
+ // Hover over the matching element.
+ //
+ // # Details
+ //
+ // This method hovers over the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 2. Scroll the element into view if needed.
+ // 3. Use [Page.Mouse] to hover over the center of the element, or the specified “[object Object]”.
+ // 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 “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Hover(options ...LocatorHoverOptions) error
+
+ // Returns the [`element.innerHTML`].
+ //
+ // [`element.innerHTML`]: https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML
+ InnerHTML(options ...LocatorInnerHTMLOptions) (string, error)
+
+ // Returns the [`element.innerText`].
+ // **NOTE** If you need to assert text on the page, prefer [LocatorAssertions.ToHaveText] with “[object Object]”
+ // option to avoid flakiness. See [assertions guide] for more details.
+ //
+ // [`element.innerText`]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ InnerText(options ...LocatorInnerTextOptions) (string, error)
+
+ // Returns the value for the matching `<input>` or `<textarea>` or `<select>` element.
+ // **NOTE** If you need to assert input value, prefer [LocatorAssertions.ToHaveValue] to avoid flakiness. See
+ // [assertions guide] for more details.
+ //
+ // # Details
+ //
+ // Throws elements that are not an input, textarea or a select. However, if the element is inside the `<label>`
+ // element that has an associated
+ // [control], returns the value of the
+ // control.
+ //
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ InputValue(options ...LocatorInputValueOptions) (string, error)
+
+ // Returns whether the element is checked. Throws if the element is not a checkbox or radio input.
+ // **NOTE** If you need to assert that checkbox is checked, prefer [LocatorAssertions.ToBeChecked] to avoid flakiness.
+ // See [assertions guide] for more details.
+ //
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ IsChecked(options ...LocatorIsCheckedOptions) (bool, error)
+
+ // Returns whether the element is disabled, the opposite of [enabled].
+ // **NOTE** If you need to assert that an element is disabled, prefer [LocatorAssertions.ToBeDisabled] to avoid
+ // flakiness. See [assertions guide] for more details.
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ IsDisabled(options ...LocatorIsDisabledOptions) (bool, error)
+
+ // Returns whether the element is [editable]. If the target element is not an `<input>`,
+ // `<textarea>`, `<select>`, `[contenteditable]` and does not have a role allowing `[aria-readonly]`, this method
+ // throws an error.
+ // **NOTE** If you need to assert that an element is editable, prefer [LocatorAssertions.ToBeEditable] to avoid
+ // flakiness. See [assertions guide] for more details.
+ //
+ // [editable]: https://playwright.dev/docs/actionability#editable
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ IsEditable(options ...LocatorIsEditableOptions) (bool, error)
+
+ // Returns whether the element is [enabled].
+ // **NOTE** If you need to assert that an element is enabled, prefer [LocatorAssertions.ToBeEnabled] to avoid
+ // flakiness. See [assertions guide] for more details.
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ IsEnabled(options ...LocatorIsEnabledOptions) (bool, error)
+
+ // Returns whether the element is hidden, the opposite of [visible].
+ // **NOTE** If you need to assert that element is hidden, prefer [LocatorAssertions.ToBeHidden] to avoid flakiness.
+ // See [assertions guide] for more details.
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ IsHidden(options ...LocatorIsHiddenOptions) (bool, error)
+
+ // Returns whether the element is [visible].
+ // **NOTE** If you need to assert that element is visible, prefer [LocatorAssertions.ToBeVisible] to avoid flakiness.
+ // See [assertions guide] for more details.
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ IsVisible(options ...LocatorIsVisibleOptions) (bool, error)
+
+ // Returns locator to the last matching element.
+ Last() Locator
+
+ // The method finds an element matching the specified selector in the locator's subtree. It also accepts filter
+ // options, similar to [Locator.Filter] method.
+ // [Learn more about locators].
+ //
+ // selectorOrLocator: A selector or locator to use when resolving DOM element.
+ //
+ // [Learn more about locators]: https://playwright.dev/docs/locators
+ Locator(selectorOrLocator interface{}, options ...LocatorLocatorOptions) Locator
+
+ // Returns locator to the n-th matching element. It's zero based, `nth(0)` selects the first element.
+ Nth(index int) Locator
+
+ // Creates a locator matching all elements that match one or both of the two locators.
+ // Note that when both locators match something, the resulting locator will have multiple matches, potentially causing
+ // a [locator strictness] violation.
+ //
+ // locator: Alternative locator to match.
+ //
+ // [locator strictness]: https://playwright.dev/docs/locators#strictness
+ // ["strict mode violation" error]: https://playwright.dev/docs/locators#strictness
+ Or(locator Locator) Locator
+
+ // A page this locator belongs to.
+ Page() (Page, error)
+
+ // Focuses the matching element and presses a combination of the keys.
+ //
+ // # Details
+ //
+ // Focuses the element, and then uses [Keyboard.Down] and [Keyboard.Up].
+ // “[object Object]” can specify the intended
+ // [keyboardEvent.Key] value or a single character
+ // to generate the text for. A superset of the “[object Object]” values can be found
+ // [here]. Examples of the keys are:
+ // `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
+ // `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`,
+ // etc.
+ // Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`,
+ // `ControlOrMeta`. `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
+ // Holding down `Shift` will type the text that corresponds to the “[object Object]” in the upper case.
+ // If “[object Object]” is a single character, it is case-sensitive, so the values `a` and `A` will generate different
+ // respective texts.
+ // Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+T"` are supported as well. When
+ // specified with the modifier, modifier is pressed and being held while the subsequent key is being pressed.
+ //
+ // key: Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
+ //
+ // [keyboardEvent.Key]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
+ // [here]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
+ Press(key string, options ...LocatorPressOptions) error
+
+ // **NOTE** In most cases, you should use [Locator.Fill] instead. You only need to press keys one by one if there is
+ // special keyboard handling on the page.
+ // Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the
+ // text.
+ // To press a special key, like `Control` or `ArrowDown`, use [Locator.Press].
+ //
+ // text: String of characters to sequentially press into a focused element.
+ PressSequentially(text string, options ...LocatorPressSequentiallyOptions) error
+
+ // Take a screenshot of the element matching the locator.
+ //
+ // # Details
+ //
+ // This method captures a screenshot of the page, clipped to the size and position of a particular element matching
+ // the locator. If the element is covered by other elements, it will not be actually visible on the screenshot. If the
+ // element is a scrollable container, only the currently scrolled content will be visible on the screenshot.
+ // This method waits for the [actionability] checks, then scrolls element into view before taking
+ // a screenshot. If the element is detached from DOM, the method throws an error.
+ // Returns the buffer with the captured screenshot.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Screenshot(options ...LocatorScreenshotOptions) ([]byte, error)
+
+ // This method waits for [actionability] checks, then tries to scroll element into view, unless
+ // it is completely visible as defined by
+ // [IntersectionObserver]'s `ratio`.
+ // See [scrolling] for alternative ways to scroll.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [IntersectionObserver]: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
+ // [scrolling]: https://playwright.dev/docs/input#scrolling
+ ScrollIntoViewIfNeeded(options ...LocatorScrollIntoViewIfNeededOptions) error
+
+ // Selects option or options in `<select>`.
+ //
+ // # Details
+ //
+ // This method waits for [actionability] checks, waits until all specified options are present in
+ // the `<select>` element and selects these options.
+ // If the target element is not a `<select>` element, this method throws an error. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], the control will be used
+ // instead.
+ // Returns the array of option values that have been successfully selected.
+ // Triggers a `change` and `input` event once all the provided options have been selected.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ SelectOption(values SelectOptionValues, options ...LocatorSelectOptionOptions) ([]string, error)
+
+ // This method waits for [actionability] checks, then focuses the element and selects all its
+ // text content.
+ // If the element is inside the `<label>` element that has an associated
+ // [control], focuses and selects text in
+ // the control instead.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ SelectText(options ...LocatorSelectTextOptions) error
+
+ // Set the state of a checkbox or a radio element.
+ //
+ // # Details
+ //
+ // This method checks or unchecks an element by performing the following steps:
+ // 1. Ensure that matched element is a checkbox or a radio input. If not, this method throws.
+ // 2. If the element already has the right checked state, this method returns immediately.
+ // 3. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 4. Scroll the element into view if needed.
+ // 5. Use [Page.Mouse] to click in the center of the element.
+ // 6. Ensure that the element is now checked or unchecked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // checked: Whether to check or uncheck the checkbox.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ SetChecked(checked bool, options ...LocatorSetCheckedOptions) error
+
+ // Upload file or multiple files into `<input type=file>`. For inputs with a `[webkitdirectory]` attribute, only a
+ // single directory path is supported.
+ //
+ // # Details
+ //
+ // Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then
+ // they are resolved relative to the current working directory. For empty array, clears the selected files.
+ // This method expects [Locator] to point to an
+ // [input element]. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], targets the control instead.
+ //
+ // [input element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ SetInputFiles(files interface{}, options ...LocatorSetInputFilesOptions) error
+
+ // Perform a tap gesture on the element matching the locator. For examples of emulating other gestures by manually
+ // dispatching touch events, see the [emulating legacy touch events] page.
+ //
+ // # Details
+ //
+ // This method taps the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 2. Scroll the element into view if needed.
+ // 3. Use [Page.Touchscreen] to tap the center of the element, or the specified “[object Object]”.
+ // 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 “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** `element.tap()` requires that the `hasTouch` option of the browser context be set to true.
+ //
+ // [emulating legacy touch events]: https://playwright.dev/docs/touch-events
+ // [actionability]: https://playwright.dev/docs/actionability
+ Tap(options ...LocatorTapOptions) error
+
+ // Returns the [`node.textContent`].
+ // **NOTE** If you need to assert text on the page, prefer [LocatorAssertions.ToHaveText] to avoid flakiness. See
+ // [assertions guide] for more details.
+ //
+ // [`node.textContent`]: https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ TextContent(options ...LocatorTextContentOptions) (string, error)
+
+ // Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the
+ // text.
+ // To press a special key, like `Control` or `ArrowDown`, use [Locator.Press].
+ //
+ // Deprecated: In most cases, you should use [Locator.Fill] instead. You only need to press keys one by one if there is special keyboard handling on the page - in this case use [Locator.PressSequentially].
+ //
+ // text: A text to type into a focused element.
+ Type(text string, options ...LocatorTypeOptions) error
+
+ // Ensure that checkbox or radio element is unchecked.
+ //
+ // # Details
+ //
+ // This method unchecks the element by performing the following steps:
+ // 1. Ensure that element is a checkbox or a radio input. If not, this method throws. If the element is already
+ // unchecked, this method returns immediately.
+ // 2. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to click in the center of the element.
+ // 5. Ensure that the element is now unchecked. 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 “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Uncheck(options ...LocatorUncheckOptions) error
+
+ // Returns when element specified by locator satisfies the “[object Object]” option.
+ // If target element already satisfies the condition, the method returns immediately. Otherwise, waits for up to
+ // “[object Object]” milliseconds until the condition is met.
+ WaitFor(options ...LocatorWaitForOptions) error
+
+ Err() error
+}
+
+// The [LocatorAssertions] class provides assertion methods that can be used to make assertions about the [Locator]
+// state in the tests.
+type LocatorAssertions interface {
+ // Makes the assertion check for the opposite condition. For example, this code tests that the Locator doesn't contain
+ // text `"error"`:
+ Not() LocatorAssertions
+
+ // Ensures that [Locator] points to an element that is
+ // [connected] to a Document or a ShadowRoot.
+ //
+ // [connected]: https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected
+ ToBeAttached(options ...LocatorAssertionsToBeAttachedOptions) error
+
+ // Ensures the [Locator] points to a checked input.
+ ToBeChecked(options ...LocatorAssertionsToBeCheckedOptions) error
+
+ // Ensures the [Locator] points to a disabled element. Element is disabled if it has "disabled" attribute or is
+ // disabled via
+ // ['aria-disabled']. Note
+ // that only native control elements such as HTML `button`, `input`, `select`, `textarea`, `option`, `optgroup` can be
+ // disabled by setting "disabled" attribute. "disabled" attribute on other elements is ignored by the browser.
+ //
+ // ['aria-disabled']: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-disabled
+ ToBeDisabled(options ...LocatorAssertionsToBeDisabledOptions) error
+
+ // Ensures the [Locator] points to an editable element.
+ ToBeEditable(options ...LocatorAssertionsToBeEditableOptions) error
+
+ // Ensures the [Locator] points to an empty editable element or to a DOM node that has no text.
+ ToBeEmpty(options ...LocatorAssertionsToBeEmptyOptions) error
+
+ // Ensures the [Locator] points to an enabled element.
+ ToBeEnabled(options ...LocatorAssertionsToBeEnabledOptions) error
+
+ // Ensures the [Locator] points to a focused DOM node.
+ ToBeFocused(options ...LocatorAssertionsToBeFocusedOptions) error
+
+ // Ensures that [Locator] either does not resolve to any DOM node, or resolves to a
+ // [non-visible] one.
+ //
+ // [non-visible]: https://playwright.dev/docs/actionability#visible
+ ToBeHidden(options ...LocatorAssertionsToBeHiddenOptions) error
+
+ // Ensures the [Locator] points to an element that intersects viewport, according to the
+ // [intersection observer API].
+ //
+ // [intersection observer API]: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
+ ToBeInViewport(options ...LocatorAssertionsToBeInViewportOptions) error
+
+ // Ensures that [Locator] points to an attached and [visible] DOM node.
+ // To check that at least one element from the list is visible, use [Locator.First].
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ ToBeVisible(options ...LocatorAssertionsToBeVisibleOptions) error
+
+ // Ensures the [Locator] points to an element with given CSS classes. All classes from the asserted value, separated
+ // by spaces, must be present in the
+ // [Element.ClassList] in any order.
+ //
+ // expected: A string containing expected class names, separated by spaces, or a list of such strings to assert multiple
+ // elements.
+ //
+ // [Element.ClassList]: https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
+ ToContainClass(expected interface{}, options ...LocatorAssertionsToContainClassOptions) error
+
+ // Ensures the [Locator] points to an element that contains the given text. All nested elements will be considered
+ // when computing the text content of the element. You can use regular expressions for the value as well.
+ //
+ // # Details
+ //
+ // When `expected` parameter is a string, Playwright will normalize whitespaces and line breaks both in the actual
+ // text and in the expected string before matching. When regular expression is used, the actual text is matched as is.
+ //
+ // expected: Expected substring or RegExp or a list of those.
+ ToContainText(expected interface{}, options ...LocatorAssertionsToContainTextOptions) error
+
+ // Ensures the [Locator] points to an element with a given
+ // [accessible description].
+ //
+ // description: Expected accessible description.
+ //
+ // [accessible description]: https://w3c.github.io/accname/#dfn-accessible-description
+ ToHaveAccessibleDescription(description interface{}, options ...LocatorAssertionsToHaveAccessibleDescriptionOptions) error
+
+ // Ensures the [Locator] points to an element with a given
+ // [aria errormessage].
+ //
+ // errorMessage: Expected accessible error message.
+ //
+ // [aria errormessage]: https://w3c.github.io/aria/#aria-errormessage
+ ToHaveAccessibleErrorMessage(errorMessage interface{}, options ...LocatorAssertionsToHaveAccessibleErrorMessageOptions) error
+
+ // Ensures the [Locator] points to an element with a given
+ // [accessible name].
+ //
+ // name: Expected accessible name.
+ //
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ ToHaveAccessibleName(name interface{}, options ...LocatorAssertionsToHaveAccessibleNameOptions) error
+
+ // Ensures the [Locator] points to an element with given attribute.
+ //
+ // 1. name: Attribute name.
+ // 2. value: Expected attribute value.
+ ToHaveAttribute(name string, value interface{}, options ...LocatorAssertionsToHaveAttributeOptions) error
+
+ // Ensures the [Locator] points to an element with given CSS classes. When a string is provided, it must fully match
+ // the element's `class` attribute. To match individual classes use [LocatorAssertions.ToContainClass].
+ //
+ // expected: Expected class or RegExp or a list of those.
+ ToHaveClass(expected interface{}, options ...LocatorAssertionsToHaveClassOptions) error
+
+ // Ensures the [Locator] resolves to an exact number of DOM nodes.
+ //
+ // count: Expected count.
+ ToHaveCount(count int, options ...LocatorAssertionsToHaveCountOptions) error
+
+ // Ensures the [Locator] resolves to an element with the given computed CSS style.
+ //
+ // 1. name: CSS property name.
+ // 2. value: CSS property value.
+ ToHaveCSS(name string, value interface{}, options ...LocatorAssertionsToHaveCSSOptions) error
+
+ // Ensures the [Locator] points to an element with the given DOM Node ID.
+ //
+ // id: Element id.
+ ToHaveId(id interface{}, options ...LocatorAssertionsToHaveIdOptions) error
+
+ // Ensures the [Locator] points to an element with given JavaScript property. Note that this property can be of a
+ // primitive type as well as a plain serializable JavaScript object.
+ //
+ // 1. name: Property name.
+ // 2. value: Property value.
+ ToHaveJSProperty(name string, value interface{}, options ...LocatorAssertionsToHaveJSPropertyOptions) error
+
+ // Ensures the [Locator] points to an element with a given [ARIA role].
+ // Note that role is matched as a string, disregarding the ARIA role hierarchy. For example, asserting a superclass
+ // role `"checkbox"` on an element with a subclass role `"switch"` will fail.
+ //
+ // role: Required aria role.
+ //
+ // [ARIA role]: https://www.w3.org/TR/wai-aria-1.2/#roles
+ ToHaveRole(role AriaRole, options ...LocatorAssertionsToHaveRoleOptions) error
+
+ // Ensures the [Locator] points to an element with the given text. All nested elements will be considered when
+ // computing the text content of the element. You can use regular expressions for the value as well.
+ //
+ // # Details
+ //
+ // When `expected` parameter is a string, Playwright will normalize whitespaces and line breaks both in the actual
+ // text and in the expected string before matching. When regular expression is used, the actual text is matched as is.
+ //
+ // expected: Expected string or RegExp or a list of those.
+ ToHaveText(expected interface{}, options ...LocatorAssertionsToHaveTextOptions) error
+
+ // Ensures the [Locator] points to an element with the given input value. You can use regular expressions for the
+ // value as well.
+ //
+ // value: Expected value.
+ ToHaveValue(value interface{}, options ...LocatorAssertionsToHaveValueOptions) error
+
+ // Ensures the [Locator] points to multi-select/combobox (i.e. a `select` with the `multiple` attribute) and the
+ // specified values are selected.
+ //
+ // values: Expected options currently selected.
+ ToHaveValues(values []interface{}, options ...LocatorAssertionsToHaveValuesOptions) error
+
+ // Asserts that the target element matches the given [accessibility snapshot].
+ //
+ // [accessibility snapshot]: https://playwright.dev/docs/aria-snapshots
+ ToMatchAriaSnapshot(expected string, options ...LocatorAssertionsToMatchAriaSnapshotOptions) error
+}
+
+// The Mouse class operates in main-frame CSS pixels relative to the top-left corner of the viewport.
+// Every `page` object has its own Mouse, accessible with [Page.Mouse].
+type Mouse interface {
+ // Shortcut for [Mouse.Move], [Mouse.Down], [Mouse.Up].
+ //
+ // 1. x: X coordinate relative to the main frame's viewport in CSS pixels.
+ // 2. y: Y coordinate relative to the main frame's viewport in CSS pixels.
+ Click(x float64, y float64, options ...MouseClickOptions) error
+
+ // Shortcut for [Mouse.Move], [Mouse.Down], [Mouse.Up], [Mouse.Down] and [Mouse.Up].
+ //
+ // 1. x: X coordinate relative to the main frame's viewport in CSS pixels.
+ // 2. y: Y coordinate relative to the main frame's viewport in CSS pixels.
+ Dblclick(x float64, y float64, options ...MouseDblclickOptions) error
+
+ // Dispatches a `mousedown` event.
+ Down(options ...MouseDownOptions) error
+
+ // Dispatches a `mousemove` event.
+ //
+ // 1. x: X coordinate relative to the main frame's viewport in CSS pixels.
+ // 2. y: Y coordinate relative to the main frame's viewport in CSS pixels.
+ Move(x float64, y float64, options ...MouseMoveOptions) error
+
+ // Dispatches a `mouseup` event.
+ Up(options ...MouseUpOptions) error
+
+ // Dispatches a `wheel` event. This method is usually used to manually scroll the page. See
+ // [scrolling] for alternative ways to scroll.
+ // **NOTE** Wheel events may cause scrolling if they are not handled, and this method does not wait for the scrolling
+ // to finish before returning.
+ //
+ // 1. deltaX: Pixels to scroll horizontally.
+ // 2. deltaY: Pixels to scroll vertically.
+ //
+ // [scrolling]: https://playwright.dev/docs/input#scrolling
+ Wheel(deltaX float64, deltaY float64) error
+}
+
+// Page provides methods to interact with a single tab in a [Browser], or an
+// [extension background page] in Chromium. One [Browser]
+// instance might have multiple [Page] instances.
+// This example creates a page, navigates it to a URL, and then saves a screenshot:
+// The Page class emits various events (described below) which can be handled using any of Node's native
+// [`EventEmitter`] methods, such as `on`, `once` or
+// `removeListener`.
+// This example logs a message for a single page `load` event:
+// To unsubscribe from events use the `removeListener` method:
+//
+// [extension background page]: https://developer.chrome.com/extensions/background_pages
+// [`EventEmitter`]: https://nodejs.org/api/events.html#events_class_eventemitter
+type Page interface {
+ EventEmitter
+ // Playwright has ability to mock clock and passage of time.
+ Clock() Clock
+
+ // Emitted when the page closes.
+ OnClose(fn func(Page))
+
+ // 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` are available on the [ConsoleMessage] event handler argument.
+ OnConsole(fn func(ConsoleMessage))
+
+ // Emitted when the page crashes. Browser pages might crash if they try to allocate too much memory. When the page
+ // crashes, ongoing and subsequent operations will throw.
+ // The most common way to deal with crashes is to catch an exception:
+ OnCrash(fn func(Page))
+
+ // Emitted when a JavaScript dialog appears, such as `alert`, `prompt`, `confirm` or `beforeunload`. Listener **must**
+ // either [Dialog.Accept] or [Dialog.Dismiss] the dialog - otherwise the page will
+ // [freeze] waiting for the dialog,
+ // and actions like click will never finish.
+ //
+ // [freeze]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking
+ OnDialog(fn func(Dialog))
+
+ // Emitted when the JavaScript
+ // [`DOMContentLoaded`] event is dispatched.
+ //
+ // [`DOMContentLoaded`]: https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
+ OnDOMContentLoaded(fn func(Page))
+
+ // Emitted when attachment download started. User can access basic file operations on downloaded content via the
+ // passed [Download] instance.
+ OnDownload(fn func(Download))
+
+ // Emitted when a file chooser is supposed to appear, such as after clicking the `<input type=file>`. Playwright can
+ // respond to it via setting the input files using [FileChooser.SetFiles] that can be uploaded after that.
+ OnFileChooser(fn func(FileChooser))
+
+ // Emitted when a frame is attached.
+ OnFrameAttached(fn func(Frame))
+
+ // Emitted when a frame is detached.
+ OnFrameDetached(fn func(Frame))
+
+ // Emitted when a frame is navigated to a new url.
+ OnFrameNavigated(fn func(Frame))
+
+ // Emitted when the JavaScript [`load`] event is dispatched.
+ //
+ // [`load`]: https://developer.mozilla.org/en-US/docs/Web/Events/load
+ OnLoad(fn func(Page))
+
+ // Emitted when an uncaught exception happens within the page.
+ OnPageError(fn func(error))
+
+ // Emitted when the page opens a new tab or window. This event is emitted in addition to the [BrowserContext.OnPage],
+ // but only for popups relevant to this 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. 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).
+ OnPopup(fn func(Page))
+
+ // Emitted when a page issues a request. The [request] object is read-only. In order to intercept and mutate requests,
+ // see [Page.Route] or [BrowserContext.Route].
+ OnRequest(fn func(Request))
+
+ // Emitted when a request fails, for example by timing out.
+ // **NOTE** HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request
+ // will complete with [Page.OnRequestFinished] event and not with [Page.OnRequestFailed]. A request will only be
+ // considered failed when the client cannot get an HTTP response from the server, e.g. due to network error
+ // net::ERR_FAILED.
+ OnRequestFailed(fn func(Request))
+
+ // Emitted when a request finishes successfully after downloading the response body. For a successful response, the
+ // sequence of events is `request`, `response` and `requestfinished`.
+ OnRequestFinished(fn func(Request))
+
+ // Emitted when [response] status and headers are received for a request. For a successful response, the sequence of
+ // events is `request`, `response` and `requestfinished`.
+ OnResponse(fn func(Response))
+
+ // Emitted when [WebSocket] request is sent.
+ OnWebSocket(fn func(WebSocket))
+
+ // Emitted when a dedicated [WebWorker] is spawned
+ // by the page.
+ //
+ // [WebWorker]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
+ OnWorker(fn func(Worker))
+
+ // Adds a script which would be evaluated in one of the following scenarios:
+ // - Whenever the page is navigated.
+ // - Whenever the child frame is attached or navigated. In this case, the script is evaluated in the context of the
+ // newly attached frame.
+ // The script is evaluated after the document was created but before any of its scripts were run. This is useful to
+ // amend the JavaScript environment, e.g. to seed `Math.random`.
+ //
+ // script: Script to be evaluated in the page.
+ AddInitScript(script Script) error
+
+ // Adds a `<script>` tag into the page with the desired url or content. Returns the added tag when the script's onload
+ // fires or when the script content was injected into frame.
+ AddScriptTag(options PageAddScriptTagOptions) (ElementHandle, error)
+
+ // Adds a `<link rel="stylesheet">` tag into the page with the desired url or a `<style type="text/css">` tag with the
+ // content. Returns the added tag when the stylesheet's onload fires or when the CSS content was injected into frame.
+ AddStyleTag(options PageAddStyleTagOptions) (ElementHandle, error)
+
+ // Brings page to front (activates tab).
+ BringToFront() error
+
+ // This method checks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Ensure that matched element is a checkbox or a radio input. If not, this method throws. If the element is
+ // already checked, this method returns immediately.
+ // 3. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 4. Scroll the element into view if needed.
+ // 5. Use [Page.Mouse] to click in the center of the element.
+ // 6. Ensure that the element is now checked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Check] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Check(selector string, options ...PageCheckOptions) error
+
+ // This method clicks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to click in the center of the element, or the specified “[object Object]”.
+ // 5. Wait for initiated navigations to either succeed or fail, unless “[object Object]” option is set.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Click] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Click(selector string, options ...PageClickOptions) error
+
+ // If “[object Object]” is `false`, does not run any unload handlers and waits for the page to be closed. If
+ // “[object Object]” is `true` the method will run unload handlers, but will **not** wait for the page to close.
+ // By default, `page.close()` **does not** run `beforeunload` handlers.
+ // **NOTE** if “[object Object]” is passed as true, a `beforeunload` dialog might be summoned and should be handled
+ // manually via [Page.OnDialog] event.
+ Close(options ...PageCloseOptions) error
+
+ // Gets the full HTML contents of the page, including the doctype.
+ Content() (string, error)
+
+ // Get the browser context that the page belongs to.
+ Context() BrowserContext
+
+ // This method double clicks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to double click in the center of the element, or the specified “[object Object]”.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** `page.dblclick()` dispatches two `click` events and a single `dblclick` event.
+ //
+ // Deprecated: Use locator-based [Locator.Dblclick] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Dblclick(selector string, options ...PageDblclickOptions) 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. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. typ: DOM event type: `"click"`, `"dragstart"`, etc.
+ // 3. 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
+ // [WheelEvent]: https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/WheelEvent
+ // [locators]: https://playwright.dev/docs/locators
+ DispatchEvent(selector string, typ string, eventInit interface{}, options ...PageDispatchEventOptions) error
+
+ // This method drags the source element to the target element. It will first move to the source element, perform a
+ // `mousedown`, then move to the target element and perform a `mouseup`.
+ //
+ // 1. source: A selector to search for an element to drag. If there are multiple elements satisfying the selector, the first will
+ // be used.
+ // 2. target: A selector to search for an element to drop onto. If there are multiple elements satisfying the selector, the first
+ // will be used.
+ DragAndDrop(source string, target string, options ...PageDragAndDropOptions) error
+
+ // This method changes the `CSS media type` through the `media` argument, and/or the `prefers-colors-scheme` media
+ // feature, using the `colorScheme` argument.
+ EmulateMedia(options ...PageEmulateMediaOptions) error
+
+ // The method finds an element matching the specified selector within the page and passes it as a first argument to
+ // “[object Object]”. If no elements match the selector, the method throws an error. Returns the value of
+ // “[object Object]”.
+ // If “[object Object]” returns a [Promise], then [Page.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.
+ // 3. arg: Optional argument to pass to “[object Object]”.
+ EvalOnSelector(selector string, expression string, arg interface{}, options ...PageEvalOnSelectorOptions) (interface{}, error)
+
+ // The method finds all elements matching the specified selector within the page and passes an array of matched
+ // elements as a first argument to “[object Object]”. Returns the result of “[object Object]” invocation.
+ // If “[object Object]” returns a [Promise], then [Page.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.
+ // 3. arg: Optional argument to pass to “[object Object]”.
+ EvalOnSelectorAll(selector string, expression string, arg ...interface{}) (interface{}, error)
+
+ // Returns the value of the “[object Object]” invocation.
+ // If the function passed to the [Page.Evaluate] returns a [Promise], then [Page.Evaluate] would wait for the promise
+ // to resolve and return its value.
+ // If the function passed to the [Page.Evaluate] returns a non-[Serializable] value, then [Page.Evaluate] resolves to
+ // `undefined`. Playwright also supports transferring some additional values that are not serializable by `JSON`:
+ // `-0`, `NaN`, `Infinity`, `-Infinity`.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ Evaluate(expression string, arg ...interface{}) (interface{}, error)
+
+ // Returns the value of the “[object Object]” invocation as a [JSHandle].
+ // The only difference between [Page.Evaluate] and [Page.EvaluateHandle] is that [Page.EvaluateHandle] returns
+ // [JSHandle].
+ // If the function passed to the [Page.EvaluateHandle] returns a [Promise], then [Page.EvaluateHandle] would wait for
+ // the promise to resolve and return its value.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ EvaluateHandle(expression string, arg ...interface{}) (JSHandle, error)
+
+ // The method adds a function called “[object Object]” on the `window` object of every frame in this page. When
+ // called, the function executes “[object Object]” and returns a [Promise] which resolves to the return value of
+ // “[object Object]”. If the “[object Object]” returns a [Promise], it will be awaited.
+ // The first argument of the “[object Object]” function contains information about the caller: `{ browserContext:
+ // BrowserContext, page: Page, frame: Frame }`.
+ // See [BrowserContext.ExposeBinding] for the context-wide version.
+ // **NOTE** Functions installed via [Page.ExposeBinding] survive navigations.
+ //
+ // 1. name: Name of the function on the window object.
+ // 2. binding: Callback function that will be called in the Playwright's context.
+ ExposeBinding(name string, binding BindingCallFunction, handle ...bool) error
+
+ // The method adds a function called “[object Object]” on the `window` object of every frame in the page. When called,
+ // the function executes “[object Object]” and returns a [Promise] which resolves to the return value of
+ // “[object Object]”.
+ // If the “[object Object]” returns a [Promise], it will be awaited.
+ // See [BrowserContext.ExposeFunction] for context-wide exposed function.
+ // **NOTE** Functions installed via [Page.ExposeFunction] survive navigations.
+ //
+ // 1. name: Name of the function on the window object
+ // 2. binding: Callback function which will be called in Playwright's context.
+ ExposeFunction(name string, binding ExposedFunction) error
+
+ // This method waits for an element matching “[object Object]”, waits for [actionability] checks,
+ // focuses the element, fills it and triggers an `input` event after filling. Note that you can pass an empty string
+ // to clear the input field.
+ // If the target element is not an `<input>`, `<textarea>` or `[contenteditable]` element, this method throws an
+ // error. However, if the element is inside the `<label>` element that has an associated
+ // [control], the control will be filled
+ // instead.
+ // To send fine-grained keyboard events, use [Locator.PressSequentially].
+ //
+ // Deprecated: Use locator-based [Locator.Fill] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. value: Value to fill for the `<input>`, `<textarea>` or `[contenteditable]` element.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ Fill(selector string, value string, options ...PageFillOptions) error
+
+ // This method fetches an element with “[object Object]” and focuses it. If there's no element matching
+ // “[object Object]”, the method waits until a matching element appears in the DOM.
+ //
+ // Deprecated: Use locator-based [Locator.Focus] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ Focus(selector string, options ...PageFocusOptions) error
+
+ // Returns frame matching the specified criteria. Either `name` or `url` must be specified.
+ Frame(options ...PageFrameOptions) Frame
+
+ // When working with iframes, you can create a frame locator that will enter the iframe and allow selecting elements
+ // in that iframe.
+ //
+ // selector: A selector to use when resolving DOM element.
+ FrameLocator(selector string) FrameLocator
+
+ // An array of all frames attached to the page.
+ Frames() []Frame
+
+ // Returns element attribute value.
+ //
+ // Deprecated: Use locator-based [Locator.GetAttribute] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. name: Attribute name to get the value for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ GetAttribute(selector string, name string, options ...PageGetAttributeOptions) (string, error)
+
+ // Allows locating elements by their alt text.
+ //
+ // text: Text to locate the element for.
+ GetByAltText(text interface{}, options ...PageGetByAltTextOptions) Locator
+
+ // Allows locating input elements by the text of the associated `<label>` or `aria-labelledby` element, or by the
+ // `aria-label` attribute.
+ //
+ // text: Text to locate the element for.
+ GetByLabel(text interface{}, options ...PageGetByLabelOptions) Locator
+
+ // Allows locating input elements by the placeholder text.
+ //
+ // text: Text to locate the element for.
+ GetByPlaceholder(text interface{}, options ...PageGetByPlaceholderOptions) Locator
+
+ // Allows locating elements by their [ARIA role],
+ // [ARIA attributes] and
+ // [accessible name].
+ //
+ // # Details
+ //
+ // Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback
+ // about the ARIA guidelines.
+ // Many html elements have an implicitly [defined role]
+ // that is recognized by the role selector. You can find all the
+ // [supported roles here]. ARIA guidelines **do not recommend**
+ // duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
+ //
+ // role: Required aria role.
+ //
+ // [ARIA role]: https://www.w3.org/TR/wai-aria-1.2/#roles
+ // [ARIA attributes]: https://www.w3.org/TR/wai-aria-1.2/#aria-attributes
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [defined role]: https://w3c.github.io/html-aam/#html-element-role-mappings
+ // [supported roles here]: https://www.w3.org/TR/wai-aria-1.2/#role_definitions
+ GetByRole(role AriaRole, options ...PageGetByRoleOptions) Locator
+
+ // Locate element by the test id.
+ //
+ // # Details
+ //
+ // By default, the `data-testid` attribute is used as a test id. Use [Selectors.SetTestIdAttribute] to configure a
+ // different test id attribute if necessary.
+ //
+ // testId: Id to locate the element by.
+ GetByTestId(testId interface{}) Locator
+
+ // Allows locating elements that contain given text.
+ // See also [Locator.Filter] that allows to match by another criteria, like an accessible role, and then filter by the
+ // text content.
+ //
+ // # Details
+ //
+ // Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into
+ // one, turns line breaks into spaces and ignores leading and trailing whitespace.
+ // Input elements of the type `button` and `submit` are matched by their `value` instead of the text content. For
+ // example, locating by text `"Log in"` matches `<input type=button value="Log in">`.
+ //
+ // text: Text to locate the element for.
+ GetByText(text interface{}, options ...PageGetByTextOptions) Locator
+
+ // Allows locating elements by their title attribute.
+ //
+ // text: Text to locate the element for.
+ GetByTitle(text interface{}, options ...PageGetByTitleOptions) Locator
+
+ // Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of
+ // the last redirect. If cannot go back, returns `null`.
+ // Navigate to the previous page in history.
+ GoBack(options ...PageGoBackOptions) (Response, error)
+
+ // Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of
+ // the last redirect. If cannot go forward, returns `null`.
+ // Navigate to the next page in history.
+ GoForward(options ...PageGoForwardOptions) (Response, error)
+
+ // Request the page to perform garbage collection. Note that there is no guarantee that all unreachable objects will
+ // be collected.
+ // This is useful to help detect memory leaks. For example, if your page has a large object `suspect` that might be
+ // leaked, you can check that it does not leak by using a
+ // [`WeakRef`].
+ //
+ // [`WeakRef`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef
+ RequestGC() error
+
+ // Returns the main resource response. In case of multiple redirects, the navigation will resolve with the first
+ // non-redirect response.
+ // The method will throw an error if:
+ // - there's an SSL error (e.g. in case of self-signed certificates).
+ // - target URL is invalid.
+ // - the “[object Object]” is exceeded during navigation.
+ // - the remote server does not respond or is unreachable.
+ // - the main resource failed to load.
+ // The method will not throw an error when any valid HTTP status code is returned by the remote server, including 404
+ // "Not Found" and 500 "Internal Server Error". The status code for such responses can be retrieved by calling
+ // [Response.Status].
+ // **NOTE** The method either throws an error or returns a main resource response. The only exceptions are navigation
+ // to `about:blank` or navigation to the same URL with a different hash, which would succeed and return `null`.
+ // **NOTE** Headless mode doesn't support navigation to a PDF document. See the
+ // [upstream issue].
+ //
+ // url: URL to navigate page to. The url should include scheme, e.g. `https://`. When a “[object Object]” via the context
+ // options was provided and the passed URL is a path, it gets merged via the
+ // [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
+ //
+ // [upstream issue]: https://bugs.chromium.org/p/chromium/issues/detail?id=761295
+ Goto(url string, options ...PageGotoOptions) (Response, error)
+
+ // This method hovers over an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to hover over the center of the element, or the specified “[object Object]”.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Hover] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Hover(selector string, options ...PageHoverOptions) error
+
+ // Returns `element.innerHTML`.
+ //
+ // Deprecated: Use locator-based [Locator.InnerHTML] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ InnerHTML(selector string, options ...PageInnerHTMLOptions) (string, error)
+
+ // Returns `element.innerText`.
+ //
+ // Deprecated: Use locator-based [Locator.InnerText] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ InnerText(selector string, options ...PageInnerTextOptions) (string, error)
+
+ // Returns `input.value` for the selected `<input>` or `<textarea>` or `<select>` element.
+ // Throws for non-input elements. However, if the element is inside the `<label>` element that has an associated
+ // [control], returns the value of the
+ // control.
+ //
+ // Deprecated: Use locator-based [Locator.InputValue] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ InputValue(selector string, options ...PageInputValueOptions) (string, error)
+
+ // Returns whether the element is checked. Throws if the element is not a checkbox or radio input.
+ //
+ // Deprecated: Use locator-based [Locator.IsChecked] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ IsChecked(selector string, options ...PageIsCheckedOptions) (bool, error)
+
+ // Indicates that the page has been closed.
+ IsClosed() bool
+
+ // Returns whether the element is disabled, the opposite of [enabled].
+ //
+ // Deprecated: Use locator-based [Locator.IsDisabled] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [locators]: https://playwright.dev/docs/locators
+ IsDisabled(selector string, options ...PageIsDisabledOptions) (bool, error)
+
+ // Returns whether the element is [editable].
+ //
+ // Deprecated: Use locator-based [Locator.IsEditable] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [editable]: https://playwright.dev/docs/actionability#editable
+ // [locators]: https://playwright.dev/docs/locators
+ IsEditable(selector string, options ...PageIsEditableOptions) (bool, error)
+
+ // Returns whether the element is [enabled].
+ //
+ // Deprecated: Use locator-based [Locator.IsEnabled] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [locators]: https://playwright.dev/docs/locators
+ IsEnabled(selector string, options ...PageIsEnabledOptions) (bool, error)
+
+ // Returns whether the element is hidden, the opposite of [visible]. “[object Object]”
+ // that does not match any elements is considered hidden.
+ //
+ // Deprecated: Use locator-based [Locator.IsHidden] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [locators]: https://playwright.dev/docs/locators
+ IsHidden(selector string, options ...PageIsHiddenOptions) (bool, error)
+
+ // Returns whether the element is [visible]. “[object Object]” that does not match any
+ // elements is considered not visible.
+ //
+ // Deprecated: Use locator-based [Locator.IsVisible] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [locators]: https://playwright.dev/docs/locators
+ IsVisible(selector string, options ...PageIsVisibleOptions) (bool, error)
+
+ Keyboard() Keyboard
+
+ // The method returns an element locator that can be used to perform actions on this page / frame. Locator is resolved
+ // to the element immediately before performing an action, so a series of actions on the same locator can in fact be
+ // performed on different DOM elements. That would happen if the DOM structure between those actions has changed.
+ // [Learn more about locators].
+ //
+ // selector: A selector to use when resolving DOM element.
+ //
+ // [Learn more about locators]: https://playwright.dev/docs/locators
+ Locator(selector string, options ...PageLocatorOptions) Locator
+
+ // The page's main frame. Page is guaranteed to have a main frame which persists during navigations.
+ MainFrame() Frame
+
+ Mouse() Mouse
+
+ // Returns the opener for popup pages and `null` for others. If the opener has been closed already the returns `null`.
+ Opener() (Page, error)
+
+ // Pauses script execution. Playwright will stop executing the script and wait for the user to either press 'Resume'
+ // button in the page overlay or to call `playwright.resume()` in the DevTools console.
+ // User can inspect selectors or perform manual steps while paused. Resume will continue running the original script
+ // from the place it was paused.
+ // **NOTE** This method requires Playwright to be started in a headed mode, with a falsy “[object Object]” option.
+ Pause() error
+
+ // Returns the PDF buffer.
+ // `page.pdf()` generates a pdf of the page with `print` css media. To generate a pdf with `screen` media, call
+ // [Page.EmulateMedia] before calling `page.pdf()`:
+ // **NOTE** By default, `page.pdf()` generates a pdf with modified colors for printing. Use the
+ // [`-webkit-print-color-adjust`]
+ // property to force rendering of exact colors.
+ //
+ // [`-webkit-print-color-adjust`]: https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-print-color-adjust
+ PDF(options ...PagePdfOptions) ([]byte, error)
+
+ // Focuses the element, and then uses [Keyboard.Down] and [Keyboard.Up].
+ // “[object Object]” can specify the intended
+ // [keyboardEvent.Key] value or a single character
+ // to generate the text for. A superset of the “[object Object]” values can be found
+ // [here]. Examples of the keys are:
+ // `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
+ // `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`,
+ // etc.
+ // Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`,
+ // `ControlOrMeta`. `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
+ // Holding down `Shift` will type the text that corresponds to the “[object Object]” in the upper case.
+ // If “[object Object]” is a single character, it is case-sensitive, so the values `a` and `A` will generate different
+ // respective texts.
+ // Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+T"` are supported as well. When
+ // specified with the modifier, modifier is pressed and being held while the subsequent key is being pressed.
+ //
+ // Deprecated: Use locator-based [Locator.Press] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. key: Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
+ //
+ // [keyboardEvent.Key]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
+ // [here]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
+ // [locators]: https://playwright.dev/docs/locators
+ Press(selector string, key string, options ...PagePressOptions) error
+
+ // The method finds an element matching the specified selector within the page. If no elements match the selector, the
+ // return value resolves to `null`. To wait for an element on the page, use [Locator.WaitFor].
+ //
+ // Deprecated: Use locator-based [Page.Locator] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ QuerySelector(selector string, options ...PageQuerySelectorOptions) (ElementHandle, error)
+
+ // The method finds all elements matching the specified selector within the page. If no elements match the selector,
+ // the return value resolves to `[]`.
+ //
+ // Deprecated: Use locator-based [Page.Locator] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ QuerySelectorAll(selector string) ([]ElementHandle, error)
+
+ // When testing a web page, sometimes unexpected overlays like a "Sign up" dialog appear and block actions you want to
+ // automate, e.g. clicking a button. These overlays don't always show up in the same way or at the same time, making
+ // them tricky to handle in automated tests.
+ // This method lets you set up a special function, called a handler, that activates when it detects that overlay is
+ // visible. The handler's job is to remove the overlay, allowing your test to continue as if the overlay wasn't there.
+ // Things to keep in mind:
+ // - When an overlay is shown predictably, we recommend explicitly waiting for it in your test and dismissing it as
+ // a part of your normal test flow, instead of using [Page.AddLocatorHandler].
+ // - Playwright checks for the overlay every time before executing or retrying an action that requires an
+ // [actionability check], or before performing an auto-waiting assertion check. When overlay
+ // is visible, Playwright calls the handler first, and then proceeds with the action/assertion. Note that the
+ // handler is only called when you perform an action/assertion - if the overlay becomes visible but you don't
+ // perform any actions, the handler will not be triggered.
+ // - After executing the handler, Playwright will ensure that overlay that triggered the handler is not visible
+ // anymore. You can opt-out of this behavior with “[object Object]”.
+ // - The execution time of the handler counts towards the timeout of the action/assertion that executed the handler.
+ // If your handler takes too long, it might cause timeouts.
+ // - You can register multiple handlers. However, only a single handler will be running at a time. Make sure the
+ // actions within a handler don't depend on another handler.
+ // **NOTE** Running the handler will alter your page state mid-test. For example it will change the currently focused
+ // element and move the mouse. Make sure that actions that run after the handler are self-contained and do not rely on
+ // the focus and mouse state being unchanged.
+ // For example, consider a test that calls [Locator.Focus] followed by [Keyboard.Press]. If your handler clicks a
+ // button between these two actions, the focused element most likely will be wrong, and key press will happen on the
+ // unexpected element. Use [Locator.Press] instead to avoid this problem.
+ // Another example is a series of mouse actions, where [Mouse.Move] is followed by [Mouse.Down]. Again, when the
+ // handler runs between these two actions, the mouse position will be wrong during the mouse down. Prefer
+ // self-contained actions like [Locator.Click] that do not rely on the state being unchanged by a handler.
+ //
+ // 1. locator: Locator that triggers the handler.
+ // 2. handler: Function that should be run once “[object Object]” appears. This function should get rid of the element that blocks
+ // actions like click.
+ //
+ // [actionability check]: https://playwright.dev/docs/actionability
+ AddLocatorHandler(locator Locator, handler func(Locator), options ...PageAddLocatorHandlerOptions) error
+
+ // Removes all locator handlers added by [Page.AddLocatorHandler] for a specific locator.
+ //
+ // locator: Locator passed to [Page.AddLocatorHandler].
+ RemoveLocatorHandler(locator Locator) error
+
+ // This method reloads the current page, in the same way as if the user had triggered a browser refresh. Returns the
+ // main resource response. In case of multiple redirects, the navigation will resolve with the response of the last
+ // redirect.
+ Reload(options ...PageReloadOptions) (Response, error)
+
+ // API testing helper associated with this page. This method returns the same instance as [BrowserContext.Request] on
+ // the page's context. See [BrowserContext.Request] for more details.
+ Request() APIRequestContext
+
+ // Routing provides the capability to modify network requests that are made by a page.
+ // Once routing is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or
+ // aborted.
+ // **NOTE** The handler will only be called for the first url if the response is a redirect.
+ // **NOTE** [Page.Route] will not intercept requests intercepted by Service Worker. See
+ // [this] issue. We recommend disabling Service Workers when
+ // using request interception by setting “[object Object]” to `block`.
+ // **NOTE** [Page.Route] will not intercept the first request of a popup page. Use [BrowserContext.Route] instead.
+ //
+ // 1. url: A glob pattern, regex pattern, or predicate that receives a [URL] to match during routing. If “[object Object]” is
+ // set in the context options and the provided URL is a string that does not start with `*`, it is resolved using the
+ // [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
+ // 2. handler: handler function to route the request.
+ //
+ // [this]: https://github.com/microsoft/playwright/issues/1090
+ Route(url interface{}, handler routeHandler, times ...int) error
+
+ // If specified the network requests that are made in the page will be served from the HAR file. Read more about
+ // [Replaying from HAR].
+ // Playwright will not serve requests intercepted by Service Worker from the HAR file. See
+ // [this] issue. We recommend disabling Service Workers when
+ // using request interception by setting “[object Object]” to `block`.
+ //
+ // har: Path to a [HAR](http://www.softwareishard.com/blog/har-12-spec) file with prerecorded network data. If `path` is a
+ // relative path, then it is resolved relative to the current working directory.
+ //
+ // [Replaying from HAR]: https://playwright.dev/docs/mock#replaying-from-har
+ // [this]: https://github.com/microsoft/playwright/issues/1090
+ RouteFromHAR(har string, options ...PageRouteFromHAROptions) error
+
+ // This method allows to modify websocket connections that are made by the page.
+ // Note that only `WebSocket`s created after this method was called will be routed. It is recommended to call this
+ // method before navigating the page.
+ //
+ // 1. url: Only WebSockets with the url matching this pattern will be routed. A string pattern can be relative to the
+ // “[object Object]” context option.
+ // 2. handler: Handler function to route the WebSocket.
+ RouteWebSocket(url interface{}, handler func(WebSocketRoute)) error
+
+ // Returns the buffer with the captured screenshot.
+ Screenshot(options ...PageScreenshotOptions) ([]byte, error)
+
+ // This method waits for an element matching “[object Object]”, waits for [actionability] checks,
+ // waits until all specified options are present in the `<select>` element and selects these options.
+ // If the target element is not a `<select>` element, this method throws an error. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], the control will be used
+ // instead.
+ // Returns the array of option values that have been successfully selected.
+ // Triggers a `change` and `input` event once all the provided options have been selected.
+ //
+ // Deprecated: Use locator-based [Locator.SelectOption] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ SelectOption(selector string, values SelectOptionValues, options ...PageSelectOptionOptions) ([]string, error)
+
+ // This method checks or unchecks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Ensure that matched element is a checkbox or a radio input. If not, this method throws.
+ // 3. If the element already has the right checked state, this method returns immediately.
+ // 4. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 5. Scroll the element into view if needed.
+ // 6. Use [Page.Mouse] to click in the center of the element.
+ // 7. Ensure that the element is now checked or unchecked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.SetChecked] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. checked: Whether to check or uncheck the checkbox.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ SetChecked(selector string, checked bool, options ...PageSetCheckedOptions) error
+
+ // This method internally calls [document.Write()],
+ // inheriting all its specific characteristics and behaviors.
+ //
+ // html: HTML markup to assign to the page.
+ //
+ // [document.Write()]: https://developer.mozilla.org/en-US/docs/Web/API/Document/write
+ SetContent(html string, options ...PageSetContentOptions) error
+
+ // This setting will change the default maximum navigation time for the following methods and related shortcuts:
+ // - [Page.GoBack]
+ // - [Page.GoForward]
+ // - [Page.Goto]
+ // - [Page.Reload]
+ // - [Page.SetContent]
+ // - [Page.ExpectNavigation]
+ // - [Page.WaitForURL]
+ // **NOTE** [Page.SetDefaultNavigationTimeout] takes priority over [Page.SetDefaultTimeout],
+ // [BrowserContext.SetDefaultTimeout] and [BrowserContext.SetDefaultNavigationTimeout].
+ //
+ // timeout: Maximum navigation time in milliseconds
+ SetDefaultNavigationTimeout(timeout float64)
+
+ // This setting will change the default maximum time for all the methods accepting “[object Object]” option.
+ // **NOTE** [Page.SetDefaultNavigationTimeout] takes priority over [Page.SetDefaultTimeout].
+ //
+ // timeout: Maximum time in milliseconds. Pass `0` to disable timeout.
+ SetDefaultTimeout(timeout float64)
+
+ // The extra HTTP headers will be sent with every request the page initiates.
+ // **NOTE** [Page.SetExtraHTTPHeaders] does not guarantee the order of headers in the outgoing requests.
+ //
+ // headers: An object containing additional HTTP headers to be sent with every request. All header values must be strings.
+ SetExtraHTTPHeaders(headers map[string]string) error
+
+ // Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then
+ // they are resolved relative to the current working directory. For empty array, clears the selected files. For inputs
+ // with a `[webkitdirectory]` attribute, only a single directory path is supported.
+ // This method expects “[object Object]” to point to an
+ // [input element]. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], targets the control instead.
+ //
+ // Deprecated: Use locator-based [Locator.SetInputFiles] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [input element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ SetInputFiles(selector string, files interface{}, options ...PageSetInputFilesOptions) error
+
+ // In the case of multiple pages in a single browser, each page can have its own viewport size. However,
+ // [Browser.NewContext] allows to set viewport size (and more) for all pages in the context at once.
+ // [Page.SetViewportSize] will resize the page. A lot of websites don't expect phones to change size, so you should
+ // set the viewport size before navigating to the page. [Page.SetViewportSize] will also reset `screen` size, use
+ // [Browser.NewContext] with `screen` and `viewport` parameters if you need better control of these properties.
+ //
+ // 1. width: Page width in pixels.
+ // 2. height: Page height in pixels.
+ SetViewportSize(width int, height int) error
+
+ // This method taps an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Touchscreen] to tap the center of the element, or the specified “[object Object]”.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** [Page.Tap] the method will throw if “[object Object]” option of the browser context is false.
+ //
+ // Deprecated: Use locator-based [Locator.Tap] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Tap(selector string, options ...PageTapOptions) error
+
+ // Returns `element.textContent`.
+ //
+ // Deprecated: Use locator-based [Locator.TextContent] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ TextContent(selector string, options ...PageTextContentOptions) (string, error)
+
+ // Returns the page's title.
+ Title() (string, error)
+
+ Touchscreen() Touchscreen
+
+ // Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text. `page.type` can be used to
+ // send fine-grained keyboard events. To fill values in form fields, use [Page.Fill].
+ // To press a special key, like `Control` or `ArrowDown`, use [Keyboard.Press].
+ //
+ // Deprecated: In most cases, you should use [Locator.Fill] instead. You only need to press keys one by one if there is special keyboard handling on the page - in this case use [Locator.PressSequentially].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. text: A text to type into a focused element.
+ Type(selector string, text string, options ...PageTypeOptions) error
+
+ // This method unchecks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Ensure that matched element is a checkbox or a radio input. If not, this method throws. If the element is
+ // already unchecked, this method returns immediately.
+ // 3. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 4. Scroll the element into view if needed.
+ // 5. Use [Page.Mouse] to click in the center of the element.
+ // 6. Ensure that the element is now unchecked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Uncheck] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Uncheck(selector string, options ...PageUncheckOptions) error
+
+ // Removes all routes created with [Page.Route] and [Page.RouteFromHAR].
+ UnrouteAll(options ...PageUnrouteAllOptions) error
+
+ // Removes a route created with [Page.Route]. When “[object Object]” is not specified, removes all routes for the
+ // “[object Object]”.
+ //
+ // 1. url: A glob pattern, regex pattern or predicate receiving [URL] to match while routing.
+ // 2. handler: Optional handler function to route the request.
+ Unroute(url interface{}, handler ...routeHandler) error
+
+ URL() string
+
+ // Video object associated with this page.
+ Video() Video
+
+ ViewportSize() *Size
+
+ // Performs action and waits for a [ConsoleMessage] to be logged by in the page. If predicate is provided, it passes
+ // [ConsoleMessage] value into the `predicate` function and waits for `predicate(message)` to return a truthy value.
+ // Will throw an error if the page is closed before the [Page.OnConsole] event is fired.
+ ExpectConsoleMessage(cb func() error, options ...PageExpectConsoleMessageOptions) (ConsoleMessage, error)
+
+ // Performs action and waits for a new [Download]. If predicate is provided, it passes [Download] value into the
+ // `predicate` function and waits for `predicate(download)` to return a truthy value. Will throw an error if the page
+ // is closed before the download event is fired.
+ ExpectDownload(cb func() error, options ...PageExpectDownloadOptions) (Download, error)
+
+ // Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy
+ // value. Will throw an error if the page is closed before the event is fired. Returns the event data value.
+ //
+ // event: Event name, same one typically passed into `*.on(event)`.
+ ExpectEvent(event string, cb func() error, options ...PageExpectEventOptions) (interface{}, error)
+
+ // Performs action and waits for a new [FileChooser] to be created. If predicate is provided, it passes [FileChooser]
+ // value into the `predicate` function and waits for `predicate(fileChooser)` to return a truthy value. Will throw an
+ // error if the page is closed before the file chooser is opened.
+ ExpectFileChooser(cb func() error, options ...PageExpectFileChooserOptions) (FileChooser, error)
+
+ // Returns when the “[object Object]” returns a truthy value. It resolves to a JSHandle of the truthy value.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ WaitForFunction(expression string, arg interface{}, options ...PageWaitForFunctionOptions) (JSHandle, error)
+
+ // Returns when the required load state has been reached.
+ // This resolves when the page reaches a required load state, `load` by default. The navigation must have been
+ // committed when this method is called. If current document has already reached the required state, resolves
+ // immediately.
+ // **NOTE** Most of the time, this method is not needed because Playwright
+ // [auto-waits before every action].
+ //
+ // [auto-waits before every action]: https://playwright.dev/docs/actionability
+ WaitForLoadState(options ...PageWaitForLoadStateOptions) error
+
+ // Waits for the main frame navigation and returns the main resource response. In case of multiple redirects, the
+ // navigation will resolve with the response of the last redirect. In case of navigation to a different anchor or
+ // navigation due to History API usage, the navigation will resolve with `null`.
+ //
+ // Deprecated: This method is inherently racy, please use [Page.WaitForURL] instead.
+ //
+ // [History API]: https://developer.mozilla.org/en-US/docs/Web/API/History_API
+ ExpectNavigation(cb func() error, options ...PageExpectNavigationOptions) (Response, error)
+
+ // Performs action and waits for a popup [Page]. If predicate is provided, it passes [Popup] value into the
+ // `predicate` function and waits for `predicate(page)` to return a truthy value. Will throw an error if the page is
+ // closed before the popup event is fired.
+ ExpectPopup(cb func() error, options ...PageExpectPopupOptions) (Page, error)
+
+ // Waits for the matching request and returns it. See [waiting for event] for more
+ // details about events.
+ //
+ // urlOrPredicate: Request URL string, regex or predicate receiving [Request] object. When a “[object Object]” via the context options
+ // was provided and the passed URL is a path, it gets merged via the
+ // [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
+ //
+ // [waiting for event]: https://playwright.dev/docs/events#waiting-for-event
+ ExpectRequest(urlOrPredicate interface{}, cb func() error, options ...PageExpectRequestOptions) (Request, error)
+
+ // Performs action and waits for a [Request] to finish loading. If predicate is provided, it passes [Request] value
+ // into the `predicate` function and waits for `predicate(request)` to return a truthy value. Will throw an error if
+ // the page is closed before the [Page.OnRequestFinished] event is fired.
+ ExpectRequestFinished(cb func() error, options ...PageExpectRequestFinishedOptions) (Request, error)
+
+ // Returns the matched response. See [waiting for event] for more details about
+ // events.
+ //
+ // urlOrPredicate: Request URL string, regex or predicate receiving [Response] object. When a “[object Object]” via the context
+ // options was provided and the passed URL is a path, it gets merged via the
+ // [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
+ //
+ // [waiting for event]: https://playwright.dev/docs/events#waiting-for-event
+ ExpectResponse(urlOrPredicate interface{}, cb func() error, options ...PageExpectResponseOptions) (Response, error)
+
+ // Returns when element specified by selector satisfies “[object Object]” option. Returns `null` if waiting for
+ // `hidden` or `detached`.
+ // **NOTE** Playwright automatically waits for element to be ready before performing an action. Using [Locator]
+ // objects and web-first assertions makes the code wait-for-selector-free.
+ // Wait for the “[object Object]” to satisfy “[object Object]” option (either appear/disappear from dom, or become
+ // visible/hidden). If at the moment of calling the method “[object Object]” already satisfies the condition, the
+ // method will return immediately. If the selector doesn't satisfy the condition for the “[object Object]”
+ // milliseconds, the function will throw.
+ //
+ // Deprecated: Use web assertions that assert visibility or a locator-based [Locator.WaitFor] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ WaitForSelector(selector string, options ...PageWaitForSelectorOptions) (ElementHandle, error)
+
+ // Waits for the given “[object Object]” in milliseconds.
+ // Note that `page.waitForTimeout()` should only be used for debugging. Tests using the timer in production are going
+ // to be flaky. Use signals such as network events, selectors becoming visible and others instead.
+ //
+ // Deprecated: Never wait for timeout in production. Tests that wait for time are inherently flaky. Use [Locator] actions and web assertions that wait automatically.
+ //
+ // timeout: A timeout to wait for
+ WaitForTimeout(timeout float64)
+
+ // Waits for the main frame to navigate to the given URL.
+ //
+ // url: A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if
+ // the parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly
+ // equal to the string.
+ WaitForURL(url interface{}, options ...PageWaitForURLOptions) error
+
+ // Performs action and waits for a new [WebSocket]. If predicate is provided, it passes [WebSocket] value into the
+ // `predicate` function and waits for `predicate(webSocket)` to return a truthy value. Will throw an error if the page
+ // is closed before the WebSocket event is fired.
+ ExpectWebSocket(cb func() error, options ...PageExpectWebSocketOptions) (WebSocket, error)
+
+ // Performs action and waits for a new [Worker]. If predicate is provided, it passes [Worker] value into the
+ // `predicate` function and waits for `predicate(worker)` to return a truthy value. Will throw an error if the page is
+ // closed before the worker event is fired.
+ ExpectWorker(cb func() error, options ...PageExpectWorkerOptions) (Worker, error)
+
+ // This method returns all of the dedicated
+ // [WebWorkers] associated with the page.
+ // **NOTE** This does not contain ServiceWorkers
+ //
+ // [WebWorkers]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
+ Workers() []Worker
+
+ // **NOTE** In most cases, you should use [Page.ExpectEvent].
+ // Waits for given `event` to fire. If predicate is provided, it passes event's value into the `predicate` function
+ // and waits for `predicate(event)` to return a truthy value. Will throw an error if the page is closed before the
+ // `event` is fired.
+ //
+ // event: Event name, same one typically passed into `*.on(event)`.
+ WaitForEvent(event string, options ...PageWaitForEventOptions) (interface{}, error)
+}
+
+// The [PageAssertions] class provides assertion methods that can be used to make assertions about the [Page] state in
+// the tests.
+type PageAssertions interface {
+ // Makes the assertion check for the opposite condition. For example, this code tests that the page URL doesn't
+ // contain `"error"`:
+ Not() PageAssertions
+
+ // Ensures the page has the given title.
+ //
+ // titleOrRegExp: Expected title or RegExp.
+ ToHaveTitle(titleOrRegExp interface{}, options ...PageAssertionsToHaveTitleOptions) error
+
+ // Ensures the page is navigated to the given URL.
+ //
+ // urlOrRegExp: Expected URL string or RegExp.
+ ToHaveURL(urlOrRegExp interface{}, options ...PageAssertionsToHaveURLOptions) error
+}
+
+// Playwright gives you Web-First Assertions with convenience methods for creating assertions that will wait and retry
+// until the expected condition is met.
+// Consider the following example:
+// Playwright will be re-testing the node with the selector `.status` until fetched Node has the `"Submitted"` text.
+// It will be re-fetching the node and checking it over and over, until the condition is met or until the timeout is
+// reached. You can pass this timeout as an option.
+// By default, the timeout for assertions is set to 5 seconds.
+type PlaywrightAssertions interface {
+ // Creates a [APIResponseAssertions] object for the given [APIResponse].
+ //
+ // response: [APIResponse] object to use for assertions.
+ APIResponse(response APIResponse) APIResponseAssertions
+
+ // Creates a [LocatorAssertions] object for the given [Locator].
+ //
+ // locator: [Locator] object to use for assertions.
+ Locator(locator Locator) LocatorAssertions
+
+ // Creates a [PageAssertions] object for the given [Page].
+ //
+ // page: [Page] object to use for assertions.
+ Page(page Page) PageAssertions
+}
+
+// Whenever the page sends a request for a network resource the following sequence of events are emitted by [Page]:
+// - [Page.OnRequest] emitted when the request is issued by the page.
+// - [Page.OnResponse] emitted when/if the response status and headers are received for the request.
+// - [Page.OnRequestFinished] emitted when the response body is downloaded and the request is complete.
+//
+// If request fails at some point, then instead of `requestfinished` event (and possibly instead of 'response'
+// event), the [Page.OnRequestFailed] event is emitted.
+// **NOTE** HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request
+// will complete with `requestfinished` event.
+// If request gets a 'redirect' response, the request is successfully finished with the `requestfinished` event, and a
+// new request is issued to a redirected url.
+type Request interface {
+ // An object with all the request HTTP headers associated with this request. The header names are lower-cased.
+ AllHeaders() (map[string]string, error)
+
+ // The method returns `null` unless this request has failed, as reported by `requestfailed` event.
+ Failure() error
+
+ // Returns the [Frame] that initiated this request.
+ //
+ // # Details
+ //
+ // Note that in some cases the frame is not available, and this method will throw.
+ // - When request originates in the Service Worker. You can use `request.serviceWorker()` to check that.
+ // - When navigation request is issued before the corresponding frame is created. You can use
+ // [Request.IsNavigationRequest] to check that.
+ // Here is an example that handles all the cases:
+ Frame() Frame
+
+ // An object with the request HTTP headers. The header names are lower-cased. Note that this method does not return
+ // security-related headers, including cookie-related ones. You can use [Request.AllHeaders] for complete list of
+ // headers that include `cookie` information.
+ Headers() map[string]string
+
+ // An array with all the request HTTP headers associated with this request. Unlike [Request.AllHeaders], header names
+ // are NOT lower-cased. Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times.
+ HeadersArray() ([]NameValue, error)
+
+ // Returns the value of the header matching the name. The name is case-insensitive.
+ //
+ // name: Name of the header.
+ HeaderValue(name string) (string, error)
+
+ // Whether this request is driving frame's navigation.
+ // Some navigation requests are issued before the corresponding frame is created, and therefore do not have
+ // [Request.Frame] available.
+ IsNavigationRequest() bool
+
+ // Request's method (GET, POST, etc.)
+ Method() string
+
+ // Request's post body, if any.
+ PostData() (string, error)
+
+ // Request's post body in a binary form, if any.
+ PostDataBuffer() ([]byte, error)
+
+ // Returns parsed request's body for `form-urlencoded` and JSON as a fallback if any.
+ // When the response is `application/x-www-form-urlencoded` then a key/value object of the values will be returned.
+ // Otherwise it will be parsed as JSON.
+ PostDataJSON(v interface{}) error
+
+ // Request that was redirected by the server to this one, if any.
+ // When the server responds with a redirect, Playwright creates a new [Request] object. The two requests are connected
+ // by `redirectedFrom()` and `redirectedTo()` methods. When multiple server redirects has happened, it is possible to
+ // construct the whole redirect chain by repeatedly calling `redirectedFrom()`.
+ RedirectedFrom() Request
+
+ // New request issued by the browser if the server responded with redirect.
+ RedirectedTo() Request
+
+ // Contains the request's resource type as it was perceived by the rendering engine. ResourceType will be one of the
+ // following: `document`, `stylesheet`, `image`, `media`, `font`, `script`, `texttrack`, `xhr`, `fetch`,
+ // `eventsource`, `websocket`, `manifest`, `other`.
+ ResourceType() string
+
+ // Returns the matching [Response] object, or `null` if the response was not received due to error.
+ Response() (Response, error)
+
+ // Returns resource size information for given request.
+ Sizes() (*RequestSizesResult, error)
+
+ // Returns resource timing information for given request. Most of the timing values become available upon the
+ // response, `responseEnd` becomes available when request finishes. Find more information at
+ // [Resource Timing API].
+ //
+ // [Resource Timing API]: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming
+ Timing() *RequestTiming
+
+ // URL of the request.
+ URL() string
+}
+
+// [Response] class represents responses which are received by page.
+type Response interface {
+ // An object with all the response HTTP headers associated with this response.
+ AllHeaders() (map[string]string, error)
+
+ // Returns the buffer with response body.
+ Body() ([]byte, error)
+
+ // Waits for this response to finish, returns always `null`.
+ Finished() error
+
+ // Returns the [Frame] that initiated this response.
+ Frame() Frame
+
+ // Indicates whether this Response was fulfilled by a Service Worker's Fetch Handler (i.e. via
+ // [FetchEvent.RespondWith].
+ //
+ // [FetchEvent.RespondWith]: https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/respondWith)
+ FromServiceWorker() bool
+
+ // An object with the response HTTP headers. The header names are lower-cased. Note that this method does not return
+ // security-related headers, including cookie-related ones. You can use [Response.AllHeaders] for complete list of
+ // headers that include `cookie` information.
+ Headers() map[string]string
+
+ // An array with all the request HTTP headers associated with this response. Unlike [Response.AllHeaders], header
+ // names are NOT lower-cased. Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times.
+ HeadersArray() ([]NameValue, error)
+
+ // Returns the value of the header matching the name. The name is case-insensitive. If multiple headers have the same
+ // name (except `set-cookie`), they are returned as a list separated by `, `. For `set-cookie`, the `\n` separator is
+ // used. If no headers are found, `null` is returned.
+ //
+ // name: Name of the header.
+ HeaderValue(name string) (string, error)
+
+ // Returns all values of the headers matching the name, for example `set-cookie`. The name is case-insensitive.
+ //
+ // name: Name of the header.
+ HeaderValues(name string) ([]string, error)
+
+ // Returns the JSON representation of response body.
+ // This method will throw if the response body is not parsable via `JSON.parse`.
+ JSON(v interface{}) error
+
+ // Contains a boolean stating whether the response was successful (status in the range 200-299) or not.
+ Ok() bool
+
+ // Returns the matching [Request] object.
+ Request() Request
+
+ // Returns SSL and other security information.
+ SecurityDetails() (*ResponseSecurityDetailsResult, error)
+
+ // Returns the IP address and port of the server.
+ ServerAddr() (*ResponseServerAddrResult, error)
+
+ // Contains the status code of the response (e.g., 200 for a success).
+ Status() int
+
+ // Contains the status text of the response (e.g. usually an "OK" for a success).
+ StatusText() string
+
+ // Returns the text representation of response body.
+ Text() (string, error)
+
+ // Contains the URL of the response.
+ URL() string
+}
+
+// Whenever a network route is set up with [Page.Route] or [BrowserContext.Route], the `Route` object allows to handle
+// the route.
+// Learn more about [networking].
+//
+// [networking]: https://playwright.dev/docs/network
+type Route interface {
+ // Aborts the route's request.
+ Abort(errorCode ...string) error
+
+ // Sends route's request to the network with optional overrides.
+ //
+ // # Details
+ //
+ // The “[object Object]” option applies to both the routed request and any redirects it initiates. However,
+ // “[object Object]”, “[object Object]”, and “[object Object]” only apply to the original request and are not carried
+ // over to redirected requests.
+ // [Route.Continue] will immediately send the request to the network, other matching handlers won't be invoked. Use
+ // [Route.Fallback] If you want next matching handler in the chain to be invoked.
+ // **NOTE** The `Cookie` header cannot be overridden using this method. If a value is provided, it will be ignored,
+ // and the cookie will be loaded from the browser's cookie store. To set custom cookies, use
+ // [BrowserContext.AddCookies].
+ Continue(options ...RouteContinueOptions) error
+
+ // Continues route's request with optional overrides. The method is similar to [Route.Continue] with the difference
+ // that other matching handlers will be invoked before sending the request.
+ Fallback(options ...RouteFallbackOptions) error
+
+ // Performs the request and fetches result without fulfilling it, so that the response could be modified and then
+ // fulfilled.
+ //
+ // # Details
+ //
+ // Note that “[object Object]” option will apply to the fetched request as well as any redirects initiated by it. If
+ // you want to only apply “[object Object]” to the original request, but not to redirects, look into [Route.Continue]
+ // instead.
+ Fetch(options ...RouteFetchOptions) (APIResponse, error)
+
+ // Fulfills route's request with given response.
+ Fulfill(options ...RouteFulfillOptions) error
+
+ // A request to be routed.
+ Request() Request
+}
+
+// Selectors can be used to install custom selector engines. See [extensibility] for more
+// information.
+//
+// [extensibility]: https://playwright.dev/docs/extensibility
+type Selectors interface {
+ // Selectors must be registered before creating the page.
+ //
+ // 1. name: Name that is used in selectors as a prefix, e.g. `{name: 'foo'}` enables `foo=myselectorbody` selectors. May only
+ // contain `[a-zA-Z0-9_]` characters.
+ // 2. script: Script that evaluates to a selector engine instance. The script is evaluated in the page context.
+ Register(name string, script Script, options ...SelectorsRegisterOptions) error
+
+ // Defines custom attribute name to be used in [Page.GetByTestId]. `data-testid` is used by default.
+ //
+ // attributeName: Test id attribute name.
+ SetTestIdAttribute(attributeName string)
+}
+
+// The Touchscreen class operates in main-frame CSS pixels relative to the top-left corner of the viewport. Methods on
+// the touchscreen can only be used in browser contexts that have been initialized with `hasTouch` set to true.
+// This class is limited to emulating tap gestures. For examples of other gestures simulated by manually dispatching
+// touch events, see the [emulating legacy touch events] page.
+//
+// [emulating legacy touch events]: https://playwright.dev/docs/touch-events
+type Touchscreen interface {
+ // Dispatches a `touchstart` and `touchend` event with a single touch at the position
+ // (“[object Object]”,“[object Object]”).
+ // **NOTE** [Page.Tap] the method will throw if “[object Object]” option of the browser context is false.
+ //
+ // 1. x: X coordinate relative to the main frame's viewport in CSS pixels.
+ // 2. y: Y coordinate relative to the main frame's viewport in CSS pixels.
+ Tap(x int, y int) error
+}
+
+// API for collecting and saving Playwright traces. Playwright traces can be opened in
+// [Trace Viewer] after Playwright script runs.
+// Start recording a trace before performing actions. At the end, stop tracing and save it to a file.
+//
+// [Trace Viewer]: https://playwright.dev/docs/trace-viewer
+type Tracing interface {
+ // Start tracing.
+ Start(options ...TracingStartOptions) error
+
+ // Start a new trace chunk. If you'd like to record multiple traces on the same [BrowserContext], use [Tracing.Start]
+ // once, and then create multiple trace chunks with [Tracing.StartChunk] and [Tracing.StopChunk].
+ StartChunk(options ...TracingStartChunkOptions) error
+
+ // **NOTE** Use `test.step` instead when available.
+ // Creates a new group within the trace, assigning any subsequent API calls to this group, until [Tracing.GroupEnd] is
+ // called. Groups can be nested and will be visible in the trace viewer.
+ //
+ // name: Group name shown in the trace viewer.
+ Group(name string, options ...TracingGroupOptions) error
+
+ // Closes the last group created by [Tracing.Group].
+ GroupEnd() error
+
+ // Stop tracing.
+ Stop(path ...string) error
+
+ // Stop the trace chunk. See [Tracing.StartChunk] for more details about multiple trace chunks.
+ StopChunk(path ...string) error
+}
+
+// When browser context is created with the `recordVideo` option, each page has a video object associated with it.
+type Video interface {
+ // Deletes the video file. Will wait for the video to finish if necessary.
+ Delete() error
+
+ // Returns the file system path this video will be recorded to. The video is guaranteed to be written to the
+ // filesystem upon closing the browser context. This method throws when connected remotely.
+ Path() (string, error)
+
+ // Saves the video to a user-specified path. It is safe to call this method while the video is still in progress, or
+ // after the page has closed. This method waits until the page is closed and the video is fully saved.
+ //
+ // path: Path where the video should be saved.
+ SaveAs(path string) error
+}
+
+// [WebError] class represents an unhandled exception thrown in the page. It is dispatched via the
+// [BrowserContext.OnWebError] event.
+type WebError interface {
+ // The page that produced this unhandled exception, if any.
+ Page() Page
+
+ // Unhandled error that was thrown.
+ Error() error
+}
+
+// The [WebSocket] class represents WebSocket connections within a page. It provides the ability to inspect and
+// manipulate the data being transmitted and received.
+// If you want to intercept or modify WebSocket frames, consider using [WebSocketRoute].
+type WebSocket interface {
+ // Fired when the websocket closes.
+ OnClose(fn func(WebSocket))
+
+ // Fired when the websocket receives a frame.
+ OnFrameReceived(fn func([]byte))
+
+ // Fired when the websocket sends a frame.
+ OnFrameSent(fn func([]byte))
+
+ // Fired when the websocket has an error.
+ OnSocketError(fn func(string))
+
+ // Indicates that the web socket has been closed.
+ IsClosed() bool
+
+ // Contains the URL of the WebSocket.
+ URL() string
+
+ // Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy
+ // value. Will throw an error if the webSocket is closed before the event is fired. Returns the event data value.
+ //
+ // event: Event name, same one would pass into `webSocket.on(event)`.
+ ExpectEvent(event string, cb func() error, options ...WebSocketExpectEventOptions) (interface{}, error)
+
+ // **NOTE** In most cases, you should use [WebSocket.ExpectEvent].
+ // Waits for given `event` to fire. If predicate is provided, it passes event's value into the `predicate` function
+ // and waits for `predicate(event)` to return a truthy value. Will throw an error if the socket is closed before the
+ // `event` is fired.
+ //
+ // event: Event name, same one typically passed into `*.on(event)`.
+ WaitForEvent(event string, options ...WebSocketWaitForEventOptions) (interface{}, error)
+}
+
+// Whenever a [`WebSocket`] route is set up with
+// [Page.RouteWebSocket] or [BrowserContext.RouteWebSocket], the `WebSocketRoute` object allows to handle the
+// WebSocket, like an actual server would do.
+// **Mocking**
+// By default, the routed WebSocket will not connect to the server. This way, you can mock entire communcation over
+// the WebSocket. Here is an example that responds to a `"request"` with a `"response"`.
+// Since we do not call [WebSocketRoute.ConnectToServer] inside the WebSocket route handler, Playwright assumes that
+// WebSocket will be mocked, and opens the WebSocket inside the page automatically.
+// Here is another example that handles JSON messages:
+// **Intercepting**
+// Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block
+// them. Calling [WebSocketRoute.ConnectToServer] returns a server-side `WebSocketRoute` instance that you can send
+// messages to, or handle incoming messages.
+// Below is an example that modifies some messages sent by the page to the server. Messages sent from the server to
+// the page are left intact, relying on the default forwarding.
+// After connecting to the server, all **messages are forwarded** between the page and the server by default.
+// However, if you call [WebSocketRoute.OnMessage] on the original route, messages from the page to the server **will
+// not be forwarded** anymore, but should instead be handled by the “[object Object]”.
+// Similarly, calling [WebSocketRoute.OnMessage] on the server-side WebSocket will **stop forwarding messages** from
+// the server to the page, and “[object Object]” should take care of them.
+// The following example blocks some messages in both directions. Since it calls [WebSocketRoute.OnMessage] in both
+// directions, there is no automatic forwarding at all.
+//
+// [`WebSocket`]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
+type WebSocketRoute interface {
+ // Closes one side of the WebSocket connection.
+ Close(options ...WebSocketRouteCloseOptions)
+
+ // By default, routed WebSocket does not connect to the server, so you can mock entire WebSocket communication. This
+ // method connects to the actual WebSocket server, and returns the server-side [WebSocketRoute] instance, giving the
+ // ability to send and receive messages from the server.
+ // Once connected to the server:
+ // - Messages received from the server will be **automatically forwarded** to the WebSocket in the page, unless
+ // [WebSocketRoute.OnMessage] is called on the server-side `WebSocketRoute`.
+ // - Messages sent by the [`WebSocket.send()`] call
+ // in the page will be **automatically forwarded** to the server, unless [WebSocketRoute.OnMessage] is called on
+ // the original `WebSocketRoute`.
+ // See examples at the top for more details.
+ //
+ // [`WebSocket.send()`]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
+ ConnectToServer() (WebSocketRoute, error)
+
+ // Allows to handle [`WebSocket.close`].
+ // By default, closing one side of the connection, either in the page or on the server, will close the other side.
+ // However, when [WebSocketRoute.OnClose] handler is set up, the default forwarding of closure is disabled, and
+ // handler should take care of it.
+ //
+ // handler: Function that will handle WebSocket closure. Received an optional
+ // [close code](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code) and an optional
+ // [close reason](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#reason).
+ //
+ // [`WebSocket.close`]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close
+ OnClose(handler func(*int, *string))
+
+ // This method allows to handle messages that are sent by the WebSocket, either from the page or from the server.
+ // When called on the original WebSocket route, this method handles messages sent from the page. You can handle this
+ // messages by responding to them with [WebSocketRoute.Send], forwarding them to the server-side connection returned
+ // by [WebSocketRoute.ConnectToServer] or do something else.
+ // Once this method is called, messages are not automatically forwarded to the server or to the page - you should do
+ // that manually by calling [WebSocketRoute.Send]. See examples at the top for more details.
+ // Calling this method again will override the handler with a new one.
+ //
+ // handler: Function that will handle messages.
+ OnMessage(handler func(interface{}))
+
+ // Sends a message to the WebSocket. When called on the original WebSocket, sends the message to the page. When called
+ // on the result of [WebSocketRoute.ConnectToServer], sends the message to the server. See examples at the top for
+ // more details.
+ //
+ // message: Message to send.
+ Send(message interface{})
+
+ // URL of the WebSocket created in the page.
+ URL() string
+}
+
+// The Worker class represents a [WebWorker].
+// `worker` event is emitted on the page object to signal a worker creation. `close` event is emitted on the worker
+// object when the worker is gone.
+//
+// [WebWorker]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
+type Worker interface {
+ // Emitted when this dedicated [WebWorker] is
+ // terminated.
+ //
+ // [WebWorker]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
+ OnClose(fn func(Worker))
+
+ // Returns the return value of “[object Object]”.
+ // If the function passed to the [Worker.Evaluate] returns a [Promise], then [Worker.Evaluate] would wait for the
+ // promise to resolve and return its value.
+ // If the function passed to the [Worker.Evaluate] returns a non-[Serializable] value, then [Worker.Evaluate] returns
+ // `undefined`. Playwright also supports transferring some additional values that are not serializable by `JSON`:
+ // `-0`, `NaN`, `Infinity`, `-Infinity`.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ Evaluate(expression string, arg ...interface{}) (interface{}, error)
+
+ // Returns the return value of “[object Object]” as a [JSHandle].
+ // The only difference between [Worker.Evaluate] and [Worker.EvaluateHandle] is that [Worker.EvaluateHandle] returns
+ // [JSHandle].
+ // If the function passed to the [Worker.EvaluateHandle] returns a [Promise], then [Worker.EvaluateHandle] would wait
+ // for the promise to resolve and return its value.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ EvaluateHandle(expression string, arg ...interface{}) (JSHandle, error)
+
+ URL() string
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/generated-structs.go b/vendor/github.com/playwright-community/playwright-go/generated-structs.go
new file mode 100644
index 0000000..7a90f5a
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/generated-structs.go
@@ -0,0 +1,4364 @@
+package playwright
+
+type APIRequestNewContextOptions struct {
+ // Methods like [APIRequestContext.Get] take the base URL into consideration by using the
+ // [`URL()`] constructor for building the corresponding URL.
+ // Examples:
+ // - baseURL: `http://localhost:3000` and sending request to `/bar.html` results in `http://localhost:3000/bar.html`
+ // - baseURL: `http://localhost:3000/foo/` and sending request to `./bar.html` results in
+ // `http://localhost:3000/foo/bar.html`
+ // - baseURL: `http://localhost:3000/foo` (without trailing slash) and navigating to `./bar.html` results in
+ // `http://localhost:3000/bar.html`
+ //
+ // [`URL()`]: https://developer.mozilla.org/en-US/docs/Web/API/URL/URL
+ BaseURL *string `json:"baseURL"`
+ // TLS Client Authentication allows the server to request a client certificate and verify it.
+ //
+ // # Details
+ //
+ // An array of client certificates to be used. Each certificate object must have either both `certPath` and `keyPath`,
+ // a single `pfxPath`, or their corresponding direct value equivalents (`cert` and `key`, or `pfx`). Optionally,
+ // `passphrase` property should be provided if the certificate is encrypted. The `origin` property should be provided
+ // with an exact match to the request origin that the certificate is valid for.
+ // **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it
+ // work by replacing `localhost` with `local.playwright`.
+ ClientCertificates []ClientCertificate `json:"clientCertificates"`
+ // An object containing additional HTTP headers to be sent with every request. Defaults to none.
+ ExtraHttpHeaders map[string]string `json:"extraHTTPHeaders"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Credentials for [HTTP authentication]. If no
+ // origin is specified, the username and password are sent to any servers upon unauthorized responses.
+ //
+ // [HTTP authentication]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
+ HttpCredentials *HttpCredentials `json:"httpCredentials"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects. This can be overwritten for each request
+ // individually.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Network proxy settings.
+ Proxy *Proxy `json:"proxy"`
+ // Populates context with given storage state. This option can be used to initialize context with logged-in
+ // information obtained via [BrowserContext.StorageState] or [APIRequestContext.StorageState]. Either a path to the
+ // file with saved storage, or the value returned by one of [BrowserContext.StorageState] or
+ // [APIRequestContext.StorageState] methods.
+ StorageState *StorageState `json:"storageState"`
+ // Populates context with given storage state. This option can be used to initialize context with logged-in
+ // information obtained via [BrowserContext.StorageState]. Path to the file with saved storage state.
+ StorageStatePath *string `json:"storageStatePath"`
+ // Maximum time in milliseconds to wait for the response. Defaults to `30000` (30 seconds). Pass `0` to disable
+ // timeout.
+ Timeout *float64 `json:"timeout"`
+ // Specific user agent to use in this context.
+ UserAgent *string `json:"userAgent"`
+}
+
+type APIRequestContextDeleteOptions struct {
+ // Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
+ // and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
+ // header will be set to `application/octet-stream` if not explicitly set.
+ Data interface{} `json:"data"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
+ // as this request body. If this parameter is specified `content-type` header will be set to
+ // `application/x-www-form-urlencoded` unless explicitly provided.
+ Form interface{} `json:"form"`
+ // Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
+ // it.
+ Headers map[string]string `json:"headers"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
+ // request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
+ // explicitly provided. File values can be passed either as
+ // [`fs.ReadStream`] or as file-like object containing file
+ // name, mime-type and its content.
+ //
+ // [`fs.ReadStream`]: https://nodejs.org/api/fs.html#fs_class_fs_readstream
+ Multipart interface{} `json:"multipart"`
+ // Query parameters to be sent with the URL.
+ Params map[string]interface{} `json:"params"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type APIRequestContextDisposeOptions struct {
+ // The reason to be reported to the operations interrupted by the context disposal.
+ Reason *string `json:"reason"`
+}
+
+type APIRequestContextFetchOptions struct {
+ // Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
+ // and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
+ // header will be set to `application/octet-stream` if not explicitly set.
+ Data interface{} `json:"data"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
+ // as this request body. If this parameter is specified `content-type` header will be set to
+ // `application/x-www-form-urlencoded` unless explicitly provided.
+ Form interface{} `json:"form"`
+ // Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
+ // it.
+ Headers map[string]string `json:"headers"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // If set changes the fetch method (e.g. [PUT] or
+ // [POST]. If not specified, GET method is used.
+ //
+ // [PUT]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT
+ // [POST]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)
+ Method *string `json:"method"`
+ // Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
+ // request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
+ // explicitly provided. File values can be passed either as
+ // [`fs.ReadStream`] or as file-like object containing file
+ // name, mime-type and its content.
+ //
+ // [`fs.ReadStream`]: https://nodejs.org/api/fs.html#fs_class_fs_readstream
+ Multipart interface{} `json:"multipart"`
+ // Query parameters to be sent with the URL.
+ Params map[string]interface{} `json:"params"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type APIRequestContextGetOptions struct {
+ // Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
+ // and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
+ // header will be set to `application/octet-stream` if not explicitly set.
+ Data interface{} `json:"data"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
+ // as this request body. If this parameter is specified `content-type` header will be set to
+ // `application/x-www-form-urlencoded` unless explicitly provided.
+ Form interface{} `json:"form"`
+ // Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
+ // it.
+ Headers map[string]string `json:"headers"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
+ // request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
+ // explicitly provided. File values can be passed either as
+ // [`fs.ReadStream`] or as file-like object containing file
+ // name, mime-type and its content.
+ //
+ // [`fs.ReadStream`]: https://nodejs.org/api/fs.html#fs_class_fs_readstream
+ Multipart interface{} `json:"multipart"`
+ // Query parameters to be sent with the URL.
+ Params map[string]interface{} `json:"params"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type APIRequestContextHeadOptions struct {
+ // Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
+ // and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
+ // header will be set to `application/octet-stream` if not explicitly set.
+ Data interface{} `json:"data"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
+ // as this request body. If this parameter is specified `content-type` header will be set to
+ // `application/x-www-form-urlencoded` unless explicitly provided.
+ Form interface{} `json:"form"`
+ // Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
+ // it.
+ Headers map[string]string `json:"headers"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
+ // request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
+ // explicitly provided. File values can be passed either as
+ // [`fs.ReadStream`] or as file-like object containing file
+ // name, mime-type and its content.
+ //
+ // [`fs.ReadStream`]: https://nodejs.org/api/fs.html#fs_class_fs_readstream
+ Multipart interface{} `json:"multipart"`
+ // Query parameters to be sent with the URL.
+ Params map[string]interface{} `json:"params"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type APIRequestContextPatchOptions struct {
+ // Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
+ // and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
+ // header will be set to `application/octet-stream` if not explicitly set.
+ Data interface{} `json:"data"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
+ // as this request body. If this parameter is specified `content-type` header will be set to
+ // `application/x-www-form-urlencoded` unless explicitly provided.
+ Form interface{} `json:"form"`
+ // Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
+ // it.
+ Headers map[string]string `json:"headers"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
+ // request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
+ // explicitly provided. File values can be passed either as
+ // [`fs.ReadStream`] or as file-like object containing file
+ // name, mime-type and its content.
+ //
+ // [`fs.ReadStream`]: https://nodejs.org/api/fs.html#fs_class_fs_readstream
+ Multipart interface{} `json:"multipart"`
+ // Query parameters to be sent with the URL.
+ Params map[string]interface{} `json:"params"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type APIRequestContextPostOptions struct {
+ // Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
+ // and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
+ // header will be set to `application/octet-stream` if not explicitly set.
+ Data interface{} `json:"data"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
+ // as this request body. If this parameter is specified `content-type` header will be set to
+ // `application/x-www-form-urlencoded` unless explicitly provided.
+ Form interface{} `json:"form"`
+ // Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
+ // it.
+ Headers map[string]string `json:"headers"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
+ // request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
+ // explicitly provided. File values can be passed either as
+ // [`fs.ReadStream`] or as file-like object containing file
+ // name, mime-type and its content.
+ //
+ // [`fs.ReadStream`]: https://nodejs.org/api/fs.html#fs_class_fs_readstream
+ Multipart interface{} `json:"multipart"`
+ // Query parameters to be sent with the URL.
+ Params map[string]interface{} `json:"params"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type APIRequestContextPutOptions struct {
+ // Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
+ // and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
+ // header will be set to `application/octet-stream` if not explicitly set.
+ Data interface{} `json:"data"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
+ // as this request body. If this parameter is specified `content-type` header will be set to
+ // `application/x-www-form-urlencoded` unless explicitly provided.
+ Form interface{} `json:"form"`
+ // Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
+ // it.
+ Headers map[string]string `json:"headers"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
+ // request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
+ // explicitly provided. File values can be passed either as
+ // [`fs.ReadStream`] or as file-like object containing file
+ // name, mime-type and its content.
+ //
+ // [`fs.ReadStream`]: https://nodejs.org/api/fs.html#fs_class_fs_readstream
+ Multipart interface{} `json:"multipart"`
+ // Query parameters to be sent with the URL.
+ Params map[string]interface{} `json:"params"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type StorageState struct {
+ Cookies []Cookie `json:"cookies"`
+ Origins []Origin `json:"origins"`
+}
+
+type NameValue struct {
+ // Name of the header.
+ Name string `json:"name"`
+ // Value of the header.
+ Value string `json:"value"`
+}
+
+type BrowserCloseOptions struct {
+ // The reason to be reported to the operations interrupted by the browser closure.
+ Reason *string `json:"reason"`
+}
+
+type BrowserNewContextOptions struct {
+ // Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted.
+ AcceptDownloads *bool `json:"acceptDownloads"`
+ // When using [Page.Goto], [Page.Route], [Page.WaitForURL], [Page.ExpectRequest], or [Page.ExpectResponse] it takes
+ // the base URL in consideration by using the [`URL()`]
+ // constructor for building the corresponding URL. Unset by default. Examples:
+ // - baseURL: `http://localhost:3000` and navigating to `/bar.html` results in `http://localhost:3000/bar.html`
+ // - baseURL: `http://localhost:3000/foo/` and navigating to `./bar.html` results in
+ // `http://localhost:3000/foo/bar.html`
+ // - baseURL: `http://localhost:3000/foo` (without trailing slash) and navigating to `./bar.html` results in
+ // `http://localhost:3000/bar.html`
+ //
+ // [`URL()`]: https://developer.mozilla.org/en-US/docs/Web/API/URL/URL
+ BaseURL *string `json:"baseURL"`
+ // Toggles bypassing page's Content-Security-Policy. Defaults to `false`.
+ BypassCSP *bool `json:"bypassCSP"`
+ // TLS Client Authentication allows the server to request a client certificate and verify it.
+ //
+ // # Details
+ //
+ // An array of client certificates to be used. Each certificate object must have either both `certPath` and `keyPath`,
+ // a single `pfxPath`, or their corresponding direct value equivalents (`cert` and `key`, or `pfx`). Optionally,
+ // `passphrase` property should be provided if the certificate is encrypted. The `origin` property should be provided
+ // with an exact match to the request origin that the certificate is valid for.
+ // **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it
+ // work by replacing `localhost` with `local.playwright`.
+ ClientCertificates []ClientCertificate `json:"clientCertificates"`
+ // Emulates [prefers-colors-scheme]
+ // media feature, supported values are `light` and `dark`. See [Page.EmulateMedia] for more details. Passing
+ // `no-override` resets emulation to system defaults. Defaults to `light`.
+ //
+ // [prefers-colors-scheme]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
+ ColorScheme *ColorScheme `json:"colorScheme"`
+ // Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
+ // [emulating devices with device scale factor].
+ //
+ // [emulating devices with device scale factor]: https://playwright.dev/docs/emulation#devices
+ DeviceScaleFactor *float64 `json:"deviceScaleFactor"`
+ // An object containing additional HTTP headers to be sent with every request. Defaults to none.
+ ExtraHttpHeaders map[string]string `json:"extraHTTPHeaders"`
+ // Emulates `forced-colors` media feature, supported values are `active`, `none`. See [Page.EmulateMedia] for
+ // more details. Passing `no-override` resets emulation to system defaults. Defaults to `none`.
+ ForcedColors *ForcedColors `json:"forcedColors"`
+ Geolocation *Geolocation `json:"geolocation"`
+ // Specifies if viewport supports touch events. Defaults to false. Learn more about
+ // [mobile emulation].
+ //
+ // [mobile emulation]: https://playwright.dev/docs/emulation#devices
+ HasTouch *bool `json:"hasTouch"`
+ // Credentials for [HTTP authentication]. If no
+ // origin is specified, the username and password are sent to any servers upon unauthorized responses.
+ //
+ // [HTTP authentication]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
+ HttpCredentials *HttpCredentials `json:"httpCredentials"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Whether the `meta viewport` tag is taken into account and touch events are enabled. isMobile is a part of device,
+ // so you don't actually need to set it manually. Defaults to `false` and is not supported in Firefox. Learn more
+ // about [mobile emulation].
+ //
+ // [mobile emulation]: https://playwright.dev/docs/emulation#ismobile
+ IsMobile *bool `json:"isMobile"`
+ // Whether or not to enable JavaScript in the context. Defaults to `true`. Learn more about
+ // [disabling JavaScript].
+ //
+ // [disabling JavaScript]: https://playwright.dev/docs/emulation#javascript-enabled
+ JavaScriptEnabled *bool `json:"javaScriptEnabled"`
+ // Specify user locale, for example `en-GB`, `de-DE`, etc. Locale will affect `navigator.language` value,
+ // `Accept-Language` request header value as well as number and date formatting rules. Defaults to the system default
+ // locale. Learn more about emulation in our [emulation guide].
+ //
+ // [emulation guide]: https://playwright.dev/docs/emulation#locale--timezone
+ Locale *string `json:"locale"`
+ // Does not enforce fixed viewport, allows resizing window in the headed mode.
+ NoViewport *bool `json:"noViewport"`
+ // Whether to emulate network being offline. Defaults to `false`. Learn more about
+ // [network emulation].
+ //
+ // [network emulation]: https://playwright.dev/docs/emulation#offline
+ Offline *bool `json:"offline"`
+ // A list of permissions to grant to all pages in this context. See [BrowserContext.GrantPermissions] for more
+ // details. Defaults to none.
+ Permissions []string `json:"permissions"`
+ // Network proxy settings to use with this context. Defaults to none.
+ Proxy *Proxy `json:"proxy"`
+ // Optional setting to control resource content management. If `omit` is specified, content is not persisted. If
+ // `attach` is specified, resources are persisted as separate files and all of these files are archived along with the
+ // HAR file. Defaults to `embed`, which stores content inline the HAR file as per HAR specification.
+ RecordHarContent *HarContentPolicy `json:"recordHarContent"`
+ // When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page,
+ // cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to `full`.
+ RecordHarMode *HarMode `json:"recordHarMode"`
+ // Optional setting to control whether to omit request content from the HAR. Defaults to `false`.
+ RecordHarOmitContent *bool `json:"recordHarOmitContent"`
+ // Enables [HAR] recording for all pages into the specified HAR file
+ // on the filesystem. If not specified, the HAR is not recorded. Make sure to call [BrowserContext.Close] for the HAR
+ // to be saved.
+ //
+ // [HAR]: http://www.softwareishard.com/blog/har-12-spec
+ RecordHarPath *string `json:"recordHarPath"`
+ RecordHarURLFilter interface{} `json:"recordHarUrlFilter"`
+ // Enables video recording for all pages into `recordVideo.dir` directory. If not specified videos are not recorded.
+ // Make sure to await [BrowserContext.Close] for videos to be saved.
+ RecordVideo *RecordVideo `json:"recordVideo"`
+ // Emulates `prefers-reduced-motion` media feature, supported values are `reduce`, `no-preference`. See
+ // [Page.EmulateMedia] for more details. Passing `no-override` resets emulation to system defaults. Defaults to
+ // `no-preference`.
+ ReducedMotion *ReducedMotion `json:"reducedMotion"`
+ // Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the
+ // “[object Object]” is set.
+ Screen *Size `json:"screen"`
+ // Whether to allow sites to register Service workers. Defaults to `allow`.
+ // - `allow`: [Service Workers] can be
+ // registered.
+ // - `block`: Playwright will block all registration of Service Workers.
+ //
+ // [Service Workers]: https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
+ ServiceWorkers *ServiceWorkerPolicy `json:"serviceWorkers"`
+ // Learn more about [storage state and auth].
+ // Populates context with given storage state. This option can be used to initialize context with logged-in
+ // information obtained via [BrowserContext.StorageState].
+ //
+ // [storage state and auth]: https://playwright.dev/docs/auth
+ StorageState *OptionalStorageState `json:"storageState"`
+ // Populates context with given storage state. This option can be used to initialize context with logged-in
+ // information obtained via [BrowserContext.StorageState]. Path to the file with saved storage state.
+ StorageStatePath *string `json:"storageStatePath"`
+ // If set to true, enables strict selectors mode for this context. In the strict selectors mode all operations on
+ // selectors that imply single target DOM element will throw when more than one element matches the selector. This
+ // option does not affect any Locator APIs (Locators are always strict). Defaults to `false`. See [Locator] to learn
+ // more about the strict mode.
+ StrictSelectors *bool `json:"strictSelectors"`
+ // Changes the timezone of the context. See
+ // [ICU's metaZones.txt]
+ // for a list of supported timezone IDs. Defaults to the system timezone.
+ //
+ // [ICU's metaZones.txt]: https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1
+ TimezoneId *string `json:"timezoneId"`
+ // Specific user agent to use in this context.
+ UserAgent *string `json:"userAgent"`
+ // Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `no_viewport` disables the fixed
+ // viewport. Learn more about [viewport emulation].
+ //
+ // [viewport emulation]: https://playwright.dev/docs/emulation#viewport
+ Viewport *Size `json:"viewport"`
+}
+
+type BrowserNewPageOptions struct {
+ // Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted.
+ AcceptDownloads *bool `json:"acceptDownloads"`
+ // When using [Page.Goto], [Page.Route], [Page.WaitForURL], [Page.ExpectRequest], or [Page.ExpectResponse] it takes
+ // the base URL in consideration by using the [`URL()`]
+ // constructor for building the corresponding URL. Unset by default. Examples:
+ // - baseURL: `http://localhost:3000` and navigating to `/bar.html` results in `http://localhost:3000/bar.html`
+ // - baseURL: `http://localhost:3000/foo/` and navigating to `./bar.html` results in
+ // `http://localhost:3000/foo/bar.html`
+ // - baseURL: `http://localhost:3000/foo` (without trailing slash) and navigating to `./bar.html` results in
+ // `http://localhost:3000/bar.html`
+ //
+ // [`URL()`]: https://developer.mozilla.org/en-US/docs/Web/API/URL/URL
+ BaseURL *string `json:"baseURL"`
+ // Toggles bypassing page's Content-Security-Policy. Defaults to `false`.
+ BypassCSP *bool `json:"bypassCSP"`
+ // TLS Client Authentication allows the server to request a client certificate and verify it.
+ //
+ // # Details
+ //
+ // An array of client certificates to be used. Each certificate object must have either both `certPath` and `keyPath`,
+ // a single `pfxPath`, or their corresponding direct value equivalents (`cert` and `key`, or `pfx`). Optionally,
+ // `passphrase` property should be provided if the certificate is encrypted. The `origin` property should be provided
+ // with an exact match to the request origin that the certificate is valid for.
+ // **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it
+ // work by replacing `localhost` with `local.playwright`.
+ ClientCertificates []ClientCertificate `json:"clientCertificates"`
+ // Emulates [prefers-colors-scheme]
+ // media feature, supported values are `light` and `dark`. See [Page.EmulateMedia] for more details. Passing
+ // `no-override` resets emulation to system defaults. Defaults to `light`.
+ //
+ // [prefers-colors-scheme]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
+ ColorScheme *ColorScheme `json:"colorScheme"`
+ // Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
+ // [emulating devices with device scale factor].
+ //
+ // [emulating devices with device scale factor]: https://playwright.dev/docs/emulation#devices
+ DeviceScaleFactor *float64 `json:"deviceScaleFactor"`
+ // An object containing additional HTTP headers to be sent with every request. Defaults to none.
+ ExtraHttpHeaders map[string]string `json:"extraHTTPHeaders"`
+ // Emulates `forced-colors` media feature, supported values are `active`, `none`. See [Page.EmulateMedia] for
+ // more details. Passing `no-override` resets emulation to system defaults. Defaults to `none`.
+ ForcedColors *ForcedColors `json:"forcedColors"`
+ Geolocation *Geolocation `json:"geolocation"`
+ // Specifies if viewport supports touch events. Defaults to false. Learn more about
+ // [mobile emulation].
+ //
+ // [mobile emulation]: https://playwright.dev/docs/emulation#devices
+ HasTouch *bool `json:"hasTouch"`
+ // Credentials for [HTTP authentication]. If no
+ // origin is specified, the username and password are sent to any servers upon unauthorized responses.
+ //
+ // [HTTP authentication]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
+ HttpCredentials *HttpCredentials `json:"httpCredentials"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Whether the `meta viewport` tag is taken into account and touch events are enabled. isMobile is a part of device,
+ // so you don't actually need to set it manually. Defaults to `false` and is not supported in Firefox. Learn more
+ // about [mobile emulation].
+ //
+ // [mobile emulation]: https://playwright.dev/docs/emulation#ismobile
+ IsMobile *bool `json:"isMobile"`
+ // Whether or not to enable JavaScript in the context. Defaults to `true`. Learn more about
+ // [disabling JavaScript].
+ //
+ // [disabling JavaScript]: https://playwright.dev/docs/emulation#javascript-enabled
+ JavaScriptEnabled *bool `json:"javaScriptEnabled"`
+ // Specify user locale, for example `en-GB`, `de-DE`, etc. Locale will affect `navigator.language` value,
+ // `Accept-Language` request header value as well as number and date formatting rules. Defaults to the system default
+ // locale. Learn more about emulation in our [emulation guide].
+ //
+ // [emulation guide]: https://playwright.dev/docs/emulation#locale--timezone
+ Locale *string `json:"locale"`
+ // Does not enforce fixed viewport, allows resizing window in the headed mode.
+ NoViewport *bool `json:"noViewport"`
+ // Whether to emulate network being offline. Defaults to `false`. Learn more about
+ // [network emulation].
+ //
+ // [network emulation]: https://playwright.dev/docs/emulation#offline
+ Offline *bool `json:"offline"`
+ // A list of permissions to grant to all pages in this context. See [BrowserContext.GrantPermissions] for more
+ // details. Defaults to none.
+ Permissions []string `json:"permissions"`
+ // Network proxy settings to use with this context. Defaults to none.
+ Proxy *Proxy `json:"proxy"`
+ // Optional setting to control resource content management. If `omit` is specified, content is not persisted. If
+ // `attach` is specified, resources are persisted as separate files and all of these files are archived along with the
+ // HAR file. Defaults to `embed`, which stores content inline the HAR file as per HAR specification.
+ RecordHarContent *HarContentPolicy `json:"recordHarContent"`
+ // When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page,
+ // cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to `full`.
+ RecordHarMode *HarMode `json:"recordHarMode"`
+ // Optional setting to control whether to omit request content from the HAR. Defaults to `false`.
+ RecordHarOmitContent *bool `json:"recordHarOmitContent"`
+ // Enables [HAR] recording for all pages into the specified HAR file
+ // on the filesystem. If not specified, the HAR is not recorded. Make sure to call [BrowserContext.Close] for the HAR
+ // to be saved.
+ //
+ // [HAR]: http://www.softwareishard.com/blog/har-12-spec
+ RecordHarPath *string `json:"recordHarPath"`
+ RecordHarURLFilter interface{} `json:"recordHarUrlFilter"`
+ // Enables video recording for all pages into `recordVideo.dir` directory. If not specified videos are not recorded.
+ // Make sure to await [BrowserContext.Close] for videos to be saved.
+ RecordVideo *RecordVideo `json:"recordVideo"`
+ // Emulates `prefers-reduced-motion` media feature, supported values are `reduce`, `no-preference`. See
+ // [Page.EmulateMedia] for more details. Passing `no-override` resets emulation to system defaults. Defaults to
+ // `no-preference`.
+ ReducedMotion *ReducedMotion `json:"reducedMotion"`
+ // Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the
+ // “[object Object]” is set.
+ Screen *Size `json:"screen"`
+ // Whether to allow sites to register Service workers. Defaults to `allow`.
+ // - `allow`: [Service Workers] can be
+ // registered.
+ // - `block`: Playwright will block all registration of Service Workers.
+ //
+ // [Service Workers]: https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
+ ServiceWorkers *ServiceWorkerPolicy `json:"serviceWorkers"`
+ // Learn more about [storage state and auth].
+ // Populates context with given storage state. This option can be used to initialize context with logged-in
+ // information obtained via [BrowserContext.StorageState].
+ //
+ // [storage state and auth]: https://playwright.dev/docs/auth
+ StorageState *OptionalStorageState `json:"storageState"`
+ // Populates context with given storage state. This option can be used to initialize context with logged-in
+ // information obtained via [BrowserContext.StorageState]. Path to the file with saved storage state.
+ StorageStatePath *string `json:"storageStatePath"`
+ // If set to true, enables strict selectors mode for this context. In the strict selectors mode all operations on
+ // selectors that imply single target DOM element will throw when more than one element matches the selector. This
+ // option does not affect any Locator APIs (Locators are always strict). Defaults to `false`. See [Locator] to learn
+ // more about the strict mode.
+ StrictSelectors *bool `json:"strictSelectors"`
+ // Changes the timezone of the context. See
+ // [ICU's metaZones.txt]
+ // for a list of supported timezone IDs. Defaults to the system timezone.
+ //
+ // [ICU's metaZones.txt]: https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1
+ TimezoneId *string `json:"timezoneId"`
+ // Specific user agent to use in this context.
+ UserAgent *string `json:"userAgent"`
+ // Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `no_viewport` disables the fixed
+ // viewport. Learn more about [viewport emulation].
+ //
+ // [viewport emulation]: https://playwright.dev/docs/emulation#viewport
+ Viewport *Size `json:"viewport"`
+}
+
+type BrowserStartTracingOptions struct {
+ // specify custom categories to use instead of default.
+ Categories []string `json:"categories"`
+ // Optional, if specified, tracing includes screenshots of the given page.
+ Page Page `json:"page"`
+ // A path to write the trace file to.
+ Path *string `json:"path"`
+ // captures screenshots in the trace.
+ Screenshots *bool `json:"screenshots"`
+}
+
+type OptionalCookie struct {
+ Name string `json:"name"`
+ Value string `json:"value"`
+ // Either url or domain / path are required. Optional.
+ URL *string `json:"url"`
+ // For the cookie to apply to all subdomains as well, prefix domain with a dot, like this: ".example.com". Either url
+ // or domain / path are required. Optional.
+ Domain *string `json:"domain"`
+ // Either url or domain / path are required Optional.
+ Path *string `json:"path"`
+ // Unix time in seconds. Optional.
+ Expires *float64 `json:"expires"`
+ // Optional.
+ HttpOnly *bool `json:"httpOnly"`
+ // Optional.
+ Secure *bool `json:"secure"`
+ // Optional.
+ SameSite *SameSiteAttribute `json:"sameSite"`
+}
+
+type Script struct {
+ // Path to the JavaScript file. If `path` is a relative path, then it is resolved relative to the current working
+ // directory. Optional.
+ Path *string `json:"path"`
+ // Raw script content. Optional.
+ Content *string `json:"content"`
+}
+
+type BrowserContextClearCookiesOptions struct {
+ // Only removes cookies with the given domain.
+ Domain interface{} `json:"domain"`
+ // Only removes cookies with the given name.
+ Name interface{} `json:"name"`
+ // Only removes cookies with the given path.
+ Path interface{} `json:"path"`
+}
+
+type BrowserContextCloseOptions struct {
+ // The reason to be reported to the operations interrupted by the context closure.
+ Reason *string `json:"reason"`
+}
+
+type Cookie struct {
+ Name string `json:"name"`
+ Value string `json:"value"`
+ Domain string `json:"domain"`
+ Path string `json:"path"`
+ // Unix time in seconds.
+ Expires float64 `json:"expires"`
+ HttpOnly bool `json:"httpOnly"`
+ Secure bool `json:"secure"`
+ SameSite *SameSiteAttribute `json:"sameSite"`
+}
+
+type BrowserContextGrantPermissionsOptions struct {
+ // The [origin] to grant permissions to, e.g. "https://example.com".
+ Origin *string `json:"origin"`
+}
+
+type BrowserContextRouteFromHAROptions struct {
+ // - If set to 'abort' any request not found in the HAR file will be aborted.
+ // - If set to 'fallback' falls through to the next route handler in the handler chain.
+ // Defaults to abort.
+ NotFound *HarNotFound `json:"notFound"`
+ // If specified, updates the given HAR with the actual network information instead of serving from file. The file is
+ // written to disk when [BrowserContext.Close] is called.
+ Update *bool `json:"update"`
+ // Optional setting to control resource content management. If `attach` is specified, resources are persisted as
+ // separate files or entries in the ZIP archive. If `embed` is specified, content is stored inline the HAR file.
+ UpdateContent *RouteFromHarUpdateContentPolicy `json:"updateContent"`
+ // When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page,
+ // cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to
+ // `minimal`.
+ UpdateMode *HarMode `json:"updateMode"`
+ // A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the
+ // pattern will be served from the HAR file. If not specified, all requests are served from the HAR file.
+ URL interface{} `json:"url"`
+}
+
+type Geolocation struct {
+ // Latitude between -90 and 90.
+ Latitude float64 `json:"latitude"`
+ // Longitude between -180 and 180.
+ Longitude float64 `json:"longitude"`
+ // Non-negative accuracy value. Defaults to `0`.
+ Accuracy *float64 `json:"accuracy"`
+}
+
+type BrowserContextUnrouteAllOptions struct {
+ // Specifies whether to wait for already running handlers and what to do if they throw errors:
+ // - `default` - do not wait for current handler calls (if any) to finish, if unrouted handler throws, it may
+ // result in unhandled error
+ // - `wait` - wait for current handler calls (if any) to finish
+ // - `ignoreErrors` - do not wait for current handler calls (if any) to finish, all errors thrown by the handlers
+ // after unrouting are silently caught
+ Behavior *UnrouteBehavior `json:"behavior"`
+}
+
+type BrowserContextExpectConsoleMessageOptions struct {
+ // Receives the [ConsoleMessage] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(ConsoleMessage) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type BrowserContextExpectEventOptions struct {
+ // Receives the event data and resolves to truthy value when the waiting should resolve.
+ Predicate interface{} `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type BrowserContextExpectPageOptions struct {
+ // Receives the [Page] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(Page) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type BrowserContextWaitForEventOptions struct {
+ // Receives the event data and resolves to truthy value when the waiting should resolve.
+ Predicate interface{} `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type BrowserTypeConnectOptions struct {
+ // This option exposes network available on the connecting client to the browser being connected to. Consists of a
+ // list of rules separated by comma.
+ // Available rules:
+ // 1. Hostname pattern, for example: `example.com`, `*.org:99`, `x.*.y.com`, `*foo.org`.
+ // 2. IP literal, for example: `127.0.0.1`, `0.0.0.0:99`, `[::1]`, `[0:0::1]:99`.
+ // 3. `<loopback>` that matches local loopback interfaces: `localhost`, `*.localhost`, `127.0.0.1`, `[::1]`.
+ // Some common examples:
+ // 4. `"*"` to expose all network.
+ // 5. `"<loopback>"` to expose localhost network.
+ // 6. `"*.test.internal-domain,*.staging.internal-domain,<loopback>"` to expose test/staging deployments and
+ // localhost.
+ ExposeNetwork *string `json:"exposeNetwork"`
+ // Additional HTTP headers to be sent with web socket connect request. Optional.
+ Headers map[string]string `json:"headers"`
+ // Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going
+ // on. Defaults to 0.
+ SlowMo *float64 `json:"slowMo"`
+ // Maximum time in milliseconds to wait for the connection to be established. Defaults to `0` (no timeout).
+ Timeout *float64 `json:"timeout"`
+}
+
+type BrowserTypeConnectOverCDPOptions struct {
+ // Additional HTTP headers to be sent with connect request. Optional.
+ Headers map[string]string `json:"headers"`
+ // Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going
+ // on. Defaults to 0.
+ SlowMo *float64 `json:"slowMo"`
+ // Maximum time in milliseconds to wait for the connection to be established. Defaults to `30000` (30 seconds). Pass
+ // `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type BrowserTypeLaunchOptions struct {
+ // **NOTE** Use custom browser args at your own risk, as some of them may break Playwright functionality.
+ // Additional arguments to pass to the browser instance. The list of Chromium flags can be found
+ // [here].
+ //
+ // [here]: https://peter.sh/experiments/chromium-command-line-switches/
+ Args []string `json:"args"`
+ // Browser distribution channel.
+ // Use "chromium" to [opt in to new headless mode].
+ // Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or
+ // "msedge-canary" to use branded [Google Chrome and Microsoft Edge].
+ //
+ // [opt in to new headless mode]: https://playwright.dev/docs/browsers#chromium-new-headless-mode
+ // [Google Chrome and Microsoft Edge]: https://playwright.dev/docs/browsers#google-chrome--microsoft-edge
+ Channel *string `json:"channel"`
+ // Enable Chromium sandboxing. Defaults to `false`.
+ ChromiumSandbox *bool `json:"chromiumSandbox"`
+ // **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the
+ // “[object Object]” option will be set `false`.
+ //
+ // Deprecated: Use [debugging tools] instead.
+ //
+ // [debugging tools]: https://playwright.dev/docs/debug
+ Devtools *bool `json:"devtools"`
+ // If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and
+ // is deleted when browser is closed. In either case, the downloads are deleted when the browser context they were
+ // created in is closed.
+ DownloadsPath *string `json:"downloadsPath"`
+ // Specify environment variables that will be visible to the browser. Defaults to `process.env`.
+ Env map[string]string `json:"env"`
+ // Path to a browser executable to run instead of the bundled one. If “[object Object]” is a relative path, then it is
+ // resolved relative to the current working directory. Note that Playwright only works with the bundled Chromium,
+ // Firefox or WebKit, use at your own risk.
+ ExecutablePath *string `json:"executablePath"`
+ // Firefox user preferences. Learn more about the Firefox user preferences at
+ // [`about:config`].
+ //
+ // [`about:config`]: https://support.mozilla.org/en-US/kb/about-config-editor-firefox
+ FirefoxUserPrefs map[string]interface{} `json:"firefoxUserPrefs"`
+ // Close the browser process on SIGHUP. Defaults to `true`.
+ HandleSIGHUP *bool `json:"handleSIGHUP"`
+ // Close the browser process on Ctrl-C. Defaults to `true`.
+ HandleSIGINT *bool `json:"handleSIGINT"`
+ // Close the browser process on SIGTERM. Defaults to `true`.
+ HandleSIGTERM *bool `json:"handleSIGTERM"`
+ // Whether to run browser in headless mode. More details for
+ // [Chromium] and
+ // [Firefox]. Defaults to `true` unless the
+ // “[object Object]” option is `true`.
+ //
+ // [Chromium]: https://developers.google.com/web/updates/2017/04/headless-chrome
+ // [Firefox]: https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/
+ Headless *bool `json:"headless"`
+ // If `true`, Playwright does not pass its own configurations args and only uses the ones from “[object Object]”.
+ // Dangerous option; use with care. Defaults to `false`.
+ IgnoreAllDefaultArgs *bool `json:"ignoreAllDefaultArgs"`
+ // If `true`, Playwright does not pass its own configurations args and only uses the ones from “[object Object]”.
+ // Dangerous option; use with care.
+ IgnoreDefaultArgs []string `json:"ignoreDefaultArgs"`
+ // Network proxy settings.
+ Proxy *Proxy `json:"proxy"`
+ // Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going
+ // on.
+ SlowMo *float64 `json:"slowMo"`
+ // Maximum time in milliseconds to wait for the browser instance to start. Defaults to `30000` (30 seconds). Pass `0`
+ // to disable timeout.
+ Timeout *float64 `json:"timeout"`
+ // If specified, traces are saved into this directory.
+ TracesDir *string `json:"tracesDir"`
+}
+
+type BrowserTypeLaunchPersistentContextOptions struct {
+ // Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted.
+ AcceptDownloads *bool `json:"acceptDownloads"`
+ // **NOTE** Use custom browser args at your own risk, as some of them may break Playwright functionality.
+ // Additional arguments to pass to the browser instance. The list of Chromium flags can be found
+ // [here].
+ //
+ // [here]: https://peter.sh/experiments/chromium-command-line-switches/
+ Args []string `json:"args"`
+ // When using [Page.Goto], [Page.Route], [Page.WaitForURL], [Page.ExpectRequest], or [Page.ExpectResponse] it takes
+ // the base URL in consideration by using the [`URL()`]
+ // constructor for building the corresponding URL. Unset by default. Examples:
+ // - baseURL: `http://localhost:3000` and navigating to `/bar.html` results in `http://localhost:3000/bar.html`
+ // - baseURL: `http://localhost:3000/foo/` and navigating to `./bar.html` results in
+ // `http://localhost:3000/foo/bar.html`
+ // - baseURL: `http://localhost:3000/foo` (without trailing slash) and navigating to `./bar.html` results in
+ // `http://localhost:3000/bar.html`
+ //
+ // [`URL()`]: https://developer.mozilla.org/en-US/docs/Web/API/URL/URL
+ BaseURL *string `json:"baseURL"`
+ // Toggles bypassing page's Content-Security-Policy. Defaults to `false`.
+ BypassCSP *bool `json:"bypassCSP"`
+ // Browser distribution channel.
+ // Use "chromium" to [opt in to new headless mode].
+ // Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or
+ // "msedge-canary" to use branded [Google Chrome and Microsoft Edge].
+ //
+ // [opt in to new headless mode]: https://playwright.dev/docs/browsers#chromium-new-headless-mode
+ // [Google Chrome and Microsoft Edge]: https://playwright.dev/docs/browsers#google-chrome--microsoft-edge
+ Channel *string `json:"channel"`
+ // Enable Chromium sandboxing. Defaults to `false`.
+ ChromiumSandbox *bool `json:"chromiumSandbox"`
+ // TLS Client Authentication allows the server to request a client certificate and verify it.
+ //
+ // # Details
+ //
+ // An array of client certificates to be used. Each certificate object must have either both `certPath` and `keyPath`,
+ // a single `pfxPath`, or their corresponding direct value equivalents (`cert` and `key`, or `pfx`). Optionally,
+ // `passphrase` property should be provided if the certificate is encrypted. The `origin` property should be provided
+ // with an exact match to the request origin that the certificate is valid for.
+ // **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it
+ // work by replacing `localhost` with `local.playwright`.
+ ClientCertificates []ClientCertificate `json:"clientCertificates"`
+ // Emulates [prefers-colors-scheme]
+ // media feature, supported values are `light` and `dark`. See [Page.EmulateMedia] for more details. Passing
+ // `no-override` resets emulation to system defaults. Defaults to `light`.
+ //
+ // [prefers-colors-scheme]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
+ ColorScheme *ColorScheme `json:"colorScheme"`
+ // Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
+ // [emulating devices with device scale factor].
+ //
+ // [emulating devices with device scale factor]: https://playwright.dev/docs/emulation#devices
+ DeviceScaleFactor *float64 `json:"deviceScaleFactor"`
+ // **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the
+ // “[object Object]” option will be set `false`.
+ //
+ // Deprecated: Use [debugging tools] instead.
+ //
+ // [debugging tools]: https://playwright.dev/docs/debug
+ Devtools *bool `json:"devtools"`
+ // If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and
+ // is deleted when browser is closed. In either case, the downloads are deleted when the browser context they were
+ // created in is closed.
+ DownloadsPath *string `json:"downloadsPath"`
+ // Specify environment variables that will be visible to the browser. Defaults to `process.env`.
+ Env map[string]string `json:"env"`
+ // Path to a browser executable to run instead of the bundled one. If “[object Object]” is a relative path, then it is
+ // resolved relative to the current working directory. Note that Playwright only works with the bundled Chromium,
+ // Firefox or WebKit, use at your own risk.
+ ExecutablePath *string `json:"executablePath"`
+ // An object containing additional HTTP headers to be sent with every request. Defaults to none.
+ ExtraHttpHeaders map[string]string `json:"extraHTTPHeaders"`
+ // Firefox user preferences. Learn more about the Firefox user preferences at
+ // [`about:config`].
+ //
+ // [`about:config`]: https://support.mozilla.org/en-US/kb/about-config-editor-firefox
+ FirefoxUserPrefs map[string]interface{} `json:"firefoxUserPrefs"`
+ // Emulates `forced-colors` media feature, supported values are `active`, `none`. See [Page.EmulateMedia] for
+ // more details. Passing `no-override` resets emulation to system defaults. Defaults to `none`.
+ ForcedColors *ForcedColors `json:"forcedColors"`
+ Geolocation *Geolocation `json:"geolocation"`
+ // Close the browser process on SIGHUP. Defaults to `true`.
+ HandleSIGHUP *bool `json:"handleSIGHUP"`
+ // Close the browser process on Ctrl-C. Defaults to `true`.
+ HandleSIGINT *bool `json:"handleSIGINT"`
+ // Close the browser process on SIGTERM. Defaults to `true`.
+ HandleSIGTERM *bool `json:"handleSIGTERM"`
+ // Specifies if viewport supports touch events. Defaults to false. Learn more about
+ // [mobile emulation].
+ //
+ // [mobile emulation]: https://playwright.dev/docs/emulation#devices
+ HasTouch *bool `json:"hasTouch"`
+ // Whether to run browser in headless mode. More details for
+ // [Chromium] and
+ // [Firefox]. Defaults to `true` unless the
+ // “[object Object]” option is `true`.
+ //
+ // [Chromium]: https://developers.google.com/web/updates/2017/04/headless-chrome
+ // [Firefox]: https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/
+ Headless *bool `json:"headless"`
+ // Credentials for [HTTP authentication]. If no
+ // origin is specified, the username and password are sent to any servers upon unauthorized responses.
+ //
+ // [HTTP authentication]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
+ HttpCredentials *HttpCredentials `json:"httpCredentials"`
+ // If `true`, Playwright does not pass its own configurations args and only uses the ones from “[object Object]”.
+ // Dangerous option; use with care. Defaults to `false`.
+ IgnoreAllDefaultArgs *bool `json:"ignoreAllDefaultArgs"`
+ // If `true`, Playwright does not pass its own configurations args and only uses the ones from “[object Object]”.
+ // Dangerous option; use with care.
+ IgnoreDefaultArgs []string `json:"ignoreDefaultArgs"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Whether the `meta viewport` tag is taken into account and touch events are enabled. isMobile is a part of device,
+ // so you don't actually need to set it manually. Defaults to `false` and is not supported in Firefox. Learn more
+ // about [mobile emulation].
+ //
+ // [mobile emulation]: https://playwright.dev/docs/emulation#ismobile
+ IsMobile *bool `json:"isMobile"`
+ // Whether or not to enable JavaScript in the context. Defaults to `true`. Learn more about
+ // [disabling JavaScript].
+ //
+ // [disabling JavaScript]: https://playwright.dev/docs/emulation#javascript-enabled
+ JavaScriptEnabled *bool `json:"javaScriptEnabled"`
+ // Specify user locale, for example `en-GB`, `de-DE`, etc. Locale will affect `navigator.language` value,
+ // `Accept-Language` request header value as well as number and date formatting rules. Defaults to the system default
+ // locale. Learn more about emulation in our [emulation guide].
+ //
+ // [emulation guide]: https://playwright.dev/docs/emulation#locale--timezone
+ Locale *string `json:"locale"`
+ // Does not enforce fixed viewport, allows resizing window in the headed mode.
+ NoViewport *bool `json:"noViewport"`
+ // Whether to emulate network being offline. Defaults to `false`. Learn more about
+ // [network emulation].
+ //
+ // [network emulation]: https://playwright.dev/docs/emulation#offline
+ Offline *bool `json:"offline"`
+ // A list of permissions to grant to all pages in this context. See [BrowserContext.GrantPermissions] for more
+ // details. Defaults to none.
+ Permissions []string `json:"permissions"`
+ // Network proxy settings.
+ Proxy *Proxy `json:"proxy"`
+ // Optional setting to control resource content management. If `omit` is specified, content is not persisted. If
+ // `attach` is specified, resources are persisted as separate files and all of these files are archived along with the
+ // HAR file. Defaults to `embed`, which stores content inline the HAR file as per HAR specification.
+ RecordHarContent *HarContentPolicy `json:"recordHarContent"`
+ // When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page,
+ // cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to `full`.
+ RecordHarMode *HarMode `json:"recordHarMode"`
+ // Optional setting to control whether to omit request content from the HAR. Defaults to `false`.
+ RecordHarOmitContent *bool `json:"recordHarOmitContent"`
+ // Enables [HAR] recording for all pages into the specified HAR file
+ // on the filesystem. If not specified, the HAR is not recorded. Make sure to call [BrowserContext.Close] for the HAR
+ // to be saved.
+ //
+ // [HAR]: http://www.softwareishard.com/blog/har-12-spec
+ RecordHarPath *string `json:"recordHarPath"`
+ RecordHarURLFilter interface{} `json:"recordHarUrlFilter"`
+ // Enables video recording for all pages into `recordVideo.dir` directory. If not specified videos are not recorded.
+ // Make sure to await [BrowserContext.Close] for videos to be saved.
+ RecordVideo *RecordVideo `json:"recordVideo"`
+ // Emulates `prefers-reduced-motion` media feature, supported values are `reduce`, `no-preference`. See
+ // [Page.EmulateMedia] for more details. Passing `no-override` resets emulation to system defaults. Defaults to
+ // `no-preference`.
+ ReducedMotion *ReducedMotion `json:"reducedMotion"`
+ // Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the
+ // “[object Object]” is set.
+ Screen *Size `json:"screen"`
+ // Whether to allow sites to register Service workers. Defaults to `allow`.
+ // - `allow`: [Service Workers] can be
+ // registered.
+ // - `block`: Playwright will block all registration of Service Workers.
+ //
+ // [Service Workers]: https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
+ ServiceWorkers *ServiceWorkerPolicy `json:"serviceWorkers"`
+ // Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going
+ // on.
+ SlowMo *float64 `json:"slowMo"`
+ // If set to true, enables strict selectors mode for this context. In the strict selectors mode all operations on
+ // selectors that imply single target DOM element will throw when more than one element matches the selector. This
+ // option does not affect any Locator APIs (Locators are always strict). Defaults to `false`. See [Locator] to learn
+ // more about the strict mode.
+ StrictSelectors *bool `json:"strictSelectors"`
+ // Maximum time in milliseconds to wait for the browser instance to start. Defaults to `30000` (30 seconds). Pass `0`
+ // to disable timeout.
+ Timeout *float64 `json:"timeout"`
+ // Changes the timezone of the context. See
+ // [ICU's metaZones.txt]
+ // for a list of supported timezone IDs. Defaults to the system timezone.
+ //
+ // [ICU's metaZones.txt]: https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1
+ TimezoneId *string `json:"timezoneId"`
+ // If specified, traces are saved into this directory.
+ TracesDir *string `json:"tracesDir"`
+ // Specific user agent to use in this context.
+ UserAgent *string `json:"userAgent"`
+ // Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `no_viewport` disables the fixed
+ // viewport. Learn more about [viewport emulation].
+ //
+ // [viewport emulation]: https://playwright.dev/docs/emulation#viewport
+ Viewport *Size `json:"viewport"`
+}
+
+type ClockInstallOptions struct {
+ // Time to initialize with, current system time by default.
+ Time interface{} `json:"time"`
+}
+
+type ConsoleMessageLocation struct {
+ // URL of the resource.
+ URL string `json:"url"`
+ // 0-based line number in the resource.
+ LineNumber int `json:"lineNumber"`
+ // 0-based column number in the resource.
+ ColumnNumber int `json:"columnNumber"`
+}
+
+type Rect struct {
+ // the x coordinate of the element in pixels.
+ X float64 `json:"x"`
+ // the y coordinate of the element in pixels.
+ Y float64 `json:"y"`
+ // the width of the element in pixels.
+ Width float64 `json:"width"`
+ // the height of the element in pixels.
+ Height float64 `json:"height"`
+}
+
+type ElementHandleCheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type ElementHandleClickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // defaults to 1. See [UIEvent.Detail].
+ ClickCount *int `json:"clickCount"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type ElementHandleDblclickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type ElementHandleFillOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleHoverOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type ElementHandleInputValueOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandlePressOptions struct {
+ // Time to wait between `keydown` and `keyup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleScreenshotOptions struct {
+ // When set to `"disabled"`, stops CSS animations, CSS transitions and Web Animations. Animations get different
+ // treatment depending on their duration:
+ // - finite animations are fast-forwarded to completion, so they'll fire `transitionend` event.
+ // - infinite animations are canceled to initial state, and then played over after the screenshot.
+ // Defaults to `"allow"` that leaves animations untouched.
+ Animations *ScreenshotAnimations `json:"animations"`
+ // When set to `"hide"`, screenshot will hide text caret. When set to `"initial"`, text caret behavior will not be
+ // changed. Defaults to `"hide"`.
+ Caret *ScreenshotCaret `json:"caret"`
+ // Specify locators that should be masked when the screenshot is taken. Masked elements will be overlaid with a pink
+ // box `#FF00FF` (customized by “[object Object]”) that completely covers its bounding box. The mask is also applied
+ // to invisible elements, see [Matching only visible elements] to
+ // disable that.
+ //
+ // [Matching only visible elements]: https://playwright.dev/docs/locators#matching-only-visible-elements
+ Mask []Locator `json:"mask"`
+ // Specify the color of the overlay box for masked elements, in
+ // [CSS color format]. Default color is pink `#FF00FF`.
+ //
+ // [CSS color format]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
+ MaskColor *string `json:"maskColor"`
+ // Hides default white background and allows capturing screenshots with transparency. Not applicable to `jpeg` images.
+ // Defaults to `false`.
+ OmitBackground *bool `json:"omitBackground"`
+ // The file path to save the image to. The screenshot type will be inferred from file extension. If “[object Object]”
+ // is a relative path, then it is resolved relative to the current working directory. If no path is provided, the
+ // image won't be saved to the disk.
+ Path *string `json:"path"`
+ // The quality of the image, between 0-100. Not applicable to `png` images.
+ Quality *int `json:"quality"`
+ // When set to `"css"`, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this
+ // will keep screenshots small. Using `"device"` option will produce a single pixel per each device pixel, so
+ // screenshots of high-dpi devices will be twice as large or even larger.
+ // Defaults to `"device"`.
+ Scale *ScreenshotScale `json:"scale"`
+ // Text of the stylesheet to apply while making the screenshot. This is where you can hide dynamic elements, make
+ // elements invisible or change their properties to help you creating repeatable screenshots. This stylesheet pierces
+ // the Shadow DOM and applies to the inner frames.
+ Style *string `json:"style"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // Specify screenshot type, defaults to `png`.
+ Type *ScreenshotType `json:"type"`
+}
+
+type ElementHandleScrollIntoViewIfNeededOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleSelectOptionOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleSelectTextOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleSetCheckedOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type ElementHandleSetInputFilesOptions struct {
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleTapOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type ElementHandleTypeOptions struct {
+ // Time to wait between key presses in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleUncheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type ElementHandleWaitForElementStateOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleWaitForSelectorOptions struct {
+ // Defaults to `visible`. Can be either:
+ // - `attached` - wait for element to be present in DOM.
+ // - `detached` - wait for element to not be present in DOM.
+ // - `visible` - wait for element to have non-empty bounding box and no `visibility:hidden`. Note that element
+ // without any content or with `display:none` has an empty bounding box and is not considered visible.
+ // - `hidden` - wait for element to be either detached from DOM, or have an empty bounding box or
+ // `visibility:hidden`. This is opposite to the `visible` option.
+ State *WaitForSelectorState `json:"state"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FileChooserSetFilesOptions struct {
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameAddScriptTagOptions struct {
+ // Raw JavaScript content to be injected into frame.
+ Content *string `json:"content"`
+ // Path to the JavaScript file to be injected into frame. If `path` is a relative path, then it is resolved relative
+ // to the current working directory.
+ Path *string `json:"path"`
+ // Script type. Use 'module' in order to load a JavaScript ES6 module. See
+ // [script] for more details.
+ //
+ // [script]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script
+ Type *string `json:"type"`
+ // URL of a script to be added.
+ URL *string `json:"url"`
+}
+
+type FrameAddStyleTagOptions struct {
+ // Raw CSS content to be injected into frame.
+ Content *string `json:"content"`
+ // Path to the CSS file to be injected into frame. If `path` is a relative path, then it is resolved relative to the
+ // current working directory.
+ Path *string `json:"path"`
+ // URL of the `<link>` tag.
+ URL *string `json:"url"`
+}
+
+type FrameCheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameClickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // defaults to 1. See [UIEvent.Detail].
+ ClickCount *int `json:"clickCount"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameDblclickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameDispatchEventOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameDragAndDropOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Clicks on the source element at this point relative to the top-left corner of the element's padding box. If not
+ // specified, some visible point of the element is used.
+ SourcePosition *Position `json:"sourcePosition"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Drops on the target element at this point relative to the top-left corner of the element's padding box. If not
+ // specified, some visible point of the element is used.
+ TargetPosition *Position `json:"targetPosition"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameEvalOnSelectorOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+}
+
+type FrameFillOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameFocusOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameGetAttributeOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameGetByAltTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameGetByLabelOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameGetByPlaceholderOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameGetByRoleOptions struct {
+ // An attribute that is usually set by `aria-checked` or native `<input type=checkbox>` controls.
+ // Learn more about [`aria-checked`].
+ //
+ // [`aria-checked`]: https://www.w3.org/TR/wai-aria-1.2/#aria-checked
+ Checked *bool `json:"checked"`
+ // An attribute that is usually set by `aria-disabled` or `disabled`.
+ // **NOTE** Unlike most other attributes, `disabled` is inherited through the DOM hierarchy. Learn more about
+ // [`aria-disabled`].
+ //
+ // [`aria-disabled`]: https://www.w3.org/TR/wai-aria-1.2/#aria-disabled
+ Disabled *bool `json:"disabled"`
+ // Whether “[object Object]” is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when
+ // “[object Object]” is a regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+ // An attribute that is usually set by `aria-expanded`.
+ // Learn more about [`aria-expanded`].
+ //
+ // [`aria-expanded`]: https://www.w3.org/TR/wai-aria-1.2/#aria-expanded
+ Expanded *bool `json:"expanded"`
+ // Option that controls whether hidden elements are matched. By default, only non-hidden elements, as
+ // [defined by ARIA], are matched by role selector.
+ // Learn more about [`aria-hidden`].
+ //
+ // [defined by ARIA]: https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion
+ // [`aria-hidden`]: https://www.w3.org/TR/wai-aria-1.2/#aria-hidden
+ IncludeHidden *bool `json:"includeHidden"`
+ // A number attribute that is usually present for roles `heading`, `listitem`, `row`, `treeitem`, with default values
+ // for `<h1>-<h6>` elements.
+ // Learn more about [`aria-level`].
+ //
+ // [`aria-level`]: https://www.w3.org/TR/wai-aria-1.2/#aria-level
+ Level *int `json:"level"`
+ // Option to match the [accessible name]. By default, matching is
+ // case-insensitive and searches for a substring, use “[object Object]” to control this behavior.
+ // Learn more about [accessible name].
+ //
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ Name interface{} `json:"name"`
+ // An attribute that is usually set by `aria-pressed`.
+ // Learn more about [`aria-pressed`].
+ //
+ // [`aria-pressed`]: https://www.w3.org/TR/wai-aria-1.2/#aria-pressed
+ Pressed *bool `json:"pressed"`
+ // An attribute that is usually set by `aria-selected`.
+ // Learn more about [`aria-selected`].
+ //
+ // [`aria-selected`]: https://www.w3.org/TR/wai-aria-1.2/#aria-selected
+ Selected *bool `json:"selected"`
+}
+
+type FrameGetByTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameGetByTitleOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameGotoOptions struct {
+ // Referer header value. If provided it will take preference over the referer header value set by
+ // [Page.SetExtraHTTPHeaders].
+ Referer *string `json:"referer"`
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type FrameHoverOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameInnerHTMLOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameInnerTextOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameInputValueOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameIsCheckedOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameIsDisabledOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameIsEditableOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameIsEnabledOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameIsHiddenOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ //
+ // Deprecated: This option is ignored. [Frame.IsHidden] does not wait for the element to become hidden and returns immediately.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameIsVisibleOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ //
+ // Deprecated: This option is ignored. [Frame.IsVisible] does not wait for the element to become visible and returns immediately.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameLocatorOptions struct {
+ // Narrows down the results of the method to those which contain elements matching this relative locator. For example,
+ // `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.
+ // Inner locator **must be relative** to the outer locator and is queried starting with the outer locator match, not
+ // the document root. For example, you can find `content` that has `div` in
+ // `<article><content><div>Playwright</div></content></article>`. However, looking for `content` that has `article
+ // div` will fail, because the inner locator must be relative and should not use any elements outside the `content`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ Has Locator `json:"has"`
+ // Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
+ // outer one. For example, `article` that does not have `div` matches `<article><span>Playwright</span></article>`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ HasNot Locator `json:"hasNot"`
+ // Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element.
+ // When passed a [string], matching is case-insensitive and searches for a substring.
+ HasNotText interface{} `json:"hasNotText"`
+ // Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When
+ // passed a [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
+ // `<article><div>Playwright</div></article>`.
+ HasText interface{} `json:"hasText"`
+}
+
+type FramePressOptions struct {
+ // Time to wait between `keydown` and `keyup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameQuerySelectorOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+}
+
+type FrameSelectOptionOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameSetCheckedOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameSetContentOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type FrameSetInputFilesOptions struct {
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameTapOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameTextContentOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameTypeOptions struct {
+ // Time to wait between key presses in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameUncheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameWaitForFunctionOptions struct {
+ // If “[object Object]” is `raf`, then “[object Object]” is constantly executed in `requestAnimationFrame` callback.
+ // If “[object Object]” is a number, then it is treated as an interval in milliseconds at which the function would be
+ // executed. Defaults to `raf`.
+ Polling interface{} `json:"polling"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameWaitForLoadStateOptions struct {
+ // Optional load state to wait for, defaults to `load`. If the state has been already reached while loading current
+ // document, the method resolves immediately. Can be one of:
+ // - `load` - wait for the `load` event to be fired.
+ // - `domcontentloaded` - wait for the `DOMContentLoaded` event to be fired.
+ // - `networkidle` - **DISCOURAGED** wait until there are no network connections for at least `500` ms. Don't use
+ // this method for testing, rely on web assertions to assess readiness instead.
+ State *LoadState `json:"state"`
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameExpectNavigationOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if
+ // the parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly
+ // equal to the string.
+ URL interface{} `json:"url"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type FrameWaitForSelectorOptions struct {
+ // Defaults to `visible`. Can be either:
+ // - `attached` - wait for element to be present in DOM.
+ // - `detached` - wait for element to not be present in DOM.
+ // - `visible` - wait for element to have non-empty bounding box and no `visibility:hidden`. Note that element
+ // without any content or with `display:none` has an empty bounding box and is not considered visible.
+ // - `hidden` - wait for element to be either detached from DOM, or have an empty bounding box or
+ // `visibility:hidden`. This is opposite to the `visible` option.
+ State *WaitForSelectorState `json:"state"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameWaitForURLOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type FrameLocatorGetByAltTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameLocatorGetByLabelOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameLocatorGetByPlaceholderOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameLocatorGetByRoleOptions struct {
+ // An attribute that is usually set by `aria-checked` or native `<input type=checkbox>` controls.
+ // Learn more about [`aria-checked`].
+ //
+ // [`aria-checked`]: https://www.w3.org/TR/wai-aria-1.2/#aria-checked
+ Checked *bool `json:"checked"`
+ // An attribute that is usually set by `aria-disabled` or `disabled`.
+ // **NOTE** Unlike most other attributes, `disabled` is inherited through the DOM hierarchy. Learn more about
+ // [`aria-disabled`].
+ //
+ // [`aria-disabled`]: https://www.w3.org/TR/wai-aria-1.2/#aria-disabled
+ Disabled *bool `json:"disabled"`
+ // Whether “[object Object]” is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when
+ // “[object Object]” is a regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+ // An attribute that is usually set by `aria-expanded`.
+ // Learn more about [`aria-expanded`].
+ //
+ // [`aria-expanded`]: https://www.w3.org/TR/wai-aria-1.2/#aria-expanded
+ Expanded *bool `json:"expanded"`
+ // Option that controls whether hidden elements are matched. By default, only non-hidden elements, as
+ // [defined by ARIA], are matched by role selector.
+ // Learn more about [`aria-hidden`].
+ //
+ // [defined by ARIA]: https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion
+ // [`aria-hidden`]: https://www.w3.org/TR/wai-aria-1.2/#aria-hidden
+ IncludeHidden *bool `json:"includeHidden"`
+ // A number attribute that is usually present for roles `heading`, `listitem`, `row`, `treeitem`, with default values
+ // for `<h1>-<h6>` elements.
+ // Learn more about [`aria-level`].
+ //
+ // [`aria-level`]: https://www.w3.org/TR/wai-aria-1.2/#aria-level
+ Level *int `json:"level"`
+ // Option to match the [accessible name]. By default, matching is
+ // case-insensitive and searches for a substring, use “[object Object]” to control this behavior.
+ // Learn more about [accessible name].
+ //
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ Name interface{} `json:"name"`
+ // An attribute that is usually set by `aria-pressed`.
+ // Learn more about [`aria-pressed`].
+ //
+ // [`aria-pressed`]: https://www.w3.org/TR/wai-aria-1.2/#aria-pressed
+ Pressed *bool `json:"pressed"`
+ // An attribute that is usually set by `aria-selected`.
+ // Learn more about [`aria-selected`].
+ //
+ // [`aria-selected`]: https://www.w3.org/TR/wai-aria-1.2/#aria-selected
+ Selected *bool `json:"selected"`
+}
+
+type FrameLocatorGetByTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameLocatorGetByTitleOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameLocatorLocatorOptions struct {
+ // Narrows down the results of the method to those which contain elements matching this relative locator. For example,
+ // `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.
+ // Inner locator **must be relative** to the outer locator and is queried starting with the outer locator match, not
+ // the document root. For example, you can find `content` that has `div` in
+ // `<article><content><div>Playwright</div></content></article>`. However, looking for `content` that has `article
+ // div` will fail, because the inner locator must be relative and should not use any elements outside the `content`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ Has Locator `json:"has"`
+ // Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
+ // outer one. For example, `article` that does not have `div` matches `<article><span>Playwright</span></article>`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ HasNot Locator `json:"hasNot"`
+ // Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element.
+ // When passed a [string], matching is case-insensitive and searches for a substring.
+ HasNotText interface{} `json:"hasNotText"`
+ // Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When
+ // passed a [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
+ // `<article><div>Playwright</div></article>`.
+ HasText interface{} `json:"hasText"`
+}
+
+type KeyboardPressOptions struct {
+ // Time to wait between `keydown` and `keyup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+}
+
+type KeyboardTypeOptions struct {
+ // Time to wait between key presses in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+}
+
+type LocatorAriaSnapshotOptions struct {
+ // Generate symbolic reference for each element. One can use `aria-ref=<ref>` locator immediately after capturing the
+ // snapshot to perform actions on the element.
+ Ref *bool `json:"ref"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorBlurOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorBoundingBoxOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorCheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorClearOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorClickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // defaults to 1. See [UIEvent.Detail].
+ ClickCount *int `json:"clickCount"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorDblclickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorDispatchEventOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorDragToOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Clicks on the source element at this point relative to the top-left corner of the element's padding box. If not
+ // specified, some visible point of the element is used.
+ SourcePosition *Position `json:"sourcePosition"`
+ // Drops on the target element at this point relative to the top-left corner of the element's padding box. If not
+ // specified, some visible point of the element is used.
+ TargetPosition *Position `json:"targetPosition"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorElementHandleOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorEvaluateOptions struct {
+ // Maximum time in milliseconds to wait for the locator before evaluating. Note that after locator is resolved,
+ // evaluation itself is not limited by the timeout. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorEvaluateHandleOptions struct {
+ // Maximum time in milliseconds to wait for the locator before evaluating. Note that after locator is resolved,
+ // evaluation itself is not limited by the timeout. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorFillOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorFilterOptions struct {
+ // Narrows down the results of the method to those which contain elements matching this relative locator. For example,
+ // `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.
+ // Inner locator **must be relative** to the outer locator and is queried starting with the outer locator match, not
+ // the document root. For example, you can find `content` that has `div` in
+ // `<article><content><div>Playwright</div></content></article>`. However, looking for `content` that has `article
+ // div` will fail, because the inner locator must be relative and should not use any elements outside the `content`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ Has Locator `json:"has"`
+ // Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
+ // outer one. For example, `article` that does not have `div` matches `<article><span>Playwright</span></article>`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ HasNot Locator `json:"hasNot"`
+ // Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element.
+ // When passed a [string], matching is case-insensitive and searches for a substring.
+ HasNotText interface{} `json:"hasNotText"`
+ // Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When
+ // passed a [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
+ // `<article><div>Playwright</div></article>`.
+ HasText interface{} `json:"hasText"`
+ // Only matches visible or invisible elements.
+ Visible *bool `json:"visible"`
+}
+
+type LocatorFocusOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorGetAttributeOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorGetByAltTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type LocatorGetByLabelOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type LocatorGetByPlaceholderOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type LocatorGetByRoleOptions struct {
+ // An attribute that is usually set by `aria-checked` or native `<input type=checkbox>` controls.
+ // Learn more about [`aria-checked`].
+ //
+ // [`aria-checked`]: https://www.w3.org/TR/wai-aria-1.2/#aria-checked
+ Checked *bool `json:"checked"`
+ // An attribute that is usually set by `aria-disabled` or `disabled`.
+ // **NOTE** Unlike most other attributes, `disabled` is inherited through the DOM hierarchy. Learn more about
+ // [`aria-disabled`].
+ //
+ // [`aria-disabled`]: https://www.w3.org/TR/wai-aria-1.2/#aria-disabled
+ Disabled *bool `json:"disabled"`
+ // Whether “[object Object]” is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when
+ // “[object Object]” is a regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+ // An attribute that is usually set by `aria-expanded`.
+ // Learn more about [`aria-expanded`].
+ //
+ // [`aria-expanded`]: https://www.w3.org/TR/wai-aria-1.2/#aria-expanded
+ Expanded *bool `json:"expanded"`
+ // Option that controls whether hidden elements are matched. By default, only non-hidden elements, as
+ // [defined by ARIA], are matched by role selector.
+ // Learn more about [`aria-hidden`].
+ //
+ // [defined by ARIA]: https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion
+ // [`aria-hidden`]: https://www.w3.org/TR/wai-aria-1.2/#aria-hidden
+ IncludeHidden *bool `json:"includeHidden"`
+ // A number attribute that is usually present for roles `heading`, `listitem`, `row`, `treeitem`, with default values
+ // for `<h1>-<h6>` elements.
+ // Learn more about [`aria-level`].
+ //
+ // [`aria-level`]: https://www.w3.org/TR/wai-aria-1.2/#aria-level
+ Level *int `json:"level"`
+ // Option to match the [accessible name]. By default, matching is
+ // case-insensitive and searches for a substring, use “[object Object]” to control this behavior.
+ // Learn more about [accessible name].
+ //
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ Name interface{} `json:"name"`
+ // An attribute that is usually set by `aria-pressed`.
+ // Learn more about [`aria-pressed`].
+ //
+ // [`aria-pressed`]: https://www.w3.org/TR/wai-aria-1.2/#aria-pressed
+ Pressed *bool `json:"pressed"`
+ // An attribute that is usually set by `aria-selected`.
+ // Learn more about [`aria-selected`].
+ //
+ // [`aria-selected`]: https://www.w3.org/TR/wai-aria-1.2/#aria-selected
+ Selected *bool `json:"selected"`
+}
+
+type LocatorGetByTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type LocatorGetByTitleOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type LocatorHoverOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorInnerHTMLOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorInnerTextOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorInputValueOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorIsCheckedOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorIsDisabledOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorIsEditableOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorIsEnabledOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorIsHiddenOptions struct {
+ //
+ // Deprecated: This option is ignored. [Locator.IsHidden] does not wait for the element to become hidden and returns immediately.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorIsVisibleOptions struct {
+ //
+ // Deprecated: This option is ignored. [Locator.IsVisible] does not wait for the element to become visible and returns immediately.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorLocatorOptions struct {
+ // Narrows down the results of the method to those which contain elements matching this relative locator. For example,
+ // `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.
+ // Inner locator **must be relative** to the outer locator and is queried starting with the outer locator match, not
+ // the document root. For example, you can find `content` that has `div` in
+ // `<article><content><div>Playwright</div></content></article>`. However, looking for `content` that has `article
+ // div` will fail, because the inner locator must be relative and should not use any elements outside the `content`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ Has Locator `json:"has"`
+ // Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
+ // outer one. For example, `article` that does not have `div` matches `<article><span>Playwright</span></article>`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ HasNot Locator `json:"hasNot"`
+ // Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element.
+ // When passed a [string], matching is case-insensitive and searches for a substring.
+ HasNotText interface{} `json:"hasNotText"`
+ // Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When
+ // passed a [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
+ // `<article><div>Playwright</div></article>`.
+ HasText interface{} `json:"hasText"`
+}
+
+type LocatorPressOptions struct {
+ // Time to wait between `keydown` and `keyup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorPressSequentiallyOptions struct {
+ // Time to wait between key presses in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorScreenshotOptions struct {
+ // When set to `"disabled"`, stops CSS animations, CSS transitions and Web Animations. Animations get different
+ // treatment depending on their duration:
+ // - finite animations are fast-forwarded to completion, so they'll fire `transitionend` event.
+ // - infinite animations are canceled to initial state, and then played over after the screenshot.
+ // Defaults to `"allow"` that leaves animations untouched.
+ Animations *ScreenshotAnimations `json:"animations"`
+ // When set to `"hide"`, screenshot will hide text caret. When set to `"initial"`, text caret behavior will not be
+ // changed. Defaults to `"hide"`.
+ Caret *ScreenshotCaret `json:"caret"`
+ // Specify locators that should be masked when the screenshot is taken. Masked elements will be overlaid with a pink
+ // box `#FF00FF` (customized by “[object Object]”) that completely covers its bounding box. The mask is also applied
+ // to invisible elements, see [Matching only visible elements] to
+ // disable that.
+ //
+ // [Matching only visible elements]: https://playwright.dev/docs/locators#matching-only-visible-elements
+ Mask []Locator `json:"mask"`
+ // Specify the color of the overlay box for masked elements, in
+ // [CSS color format]. Default color is pink `#FF00FF`.
+ //
+ // [CSS color format]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
+ MaskColor *string `json:"maskColor"`
+ // Hides default white background and allows capturing screenshots with transparency. Not applicable to `jpeg` images.
+ // Defaults to `false`.
+ OmitBackground *bool `json:"omitBackground"`
+ // The file path to save the image to. The screenshot type will be inferred from file extension. If “[object Object]”
+ // is a relative path, then it is resolved relative to the current working directory. If no path is provided, the
+ // image won't be saved to the disk.
+ Path *string `json:"path"`
+ // The quality of the image, between 0-100. Not applicable to `png` images.
+ Quality *int `json:"quality"`
+ // When set to `"css"`, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this
+ // will keep screenshots small. Using `"device"` option will produce a single pixel per each device pixel, so
+ // screenshots of high-dpi devices will be twice as large or even larger.
+ // Defaults to `"device"`.
+ Scale *ScreenshotScale `json:"scale"`
+ // Text of the stylesheet to apply while making the screenshot. This is where you can hide dynamic elements, make
+ // elements invisible or change their properties to help you creating repeatable screenshots. This stylesheet pierces
+ // the Shadow DOM and applies to the inner frames.
+ Style *string `json:"style"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // Specify screenshot type, defaults to `png`.
+ Type *ScreenshotType `json:"type"`
+}
+
+type LocatorScrollIntoViewIfNeededOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorSelectOptionOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorSelectTextOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorSetCheckedOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorSetInputFilesOptions struct {
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorTapOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorTextContentOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorTypeOptions struct {
+ // Time to wait between key presses in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorUncheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorWaitForOptions struct {
+ // Defaults to `visible`. Can be either:
+ // - `attached` - wait for element to be present in DOM.
+ // - `detached` - wait for element to not be present in DOM.
+ // - `visible` - wait for element to have non-empty bounding box and no `visibility:hidden`. Note that element
+ // without any content or with `display:none` has an empty bounding box and is not considered visible.
+ // - `hidden` - wait for element to be either detached from DOM, or have an empty bounding box or
+ // `visibility:hidden`. This is opposite to the `visible` option.
+ State *WaitForSelectorState `json:"state"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeAttachedOptions struct {
+ Attached *bool `json:"attached"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeCheckedOptions struct {
+ // Provides state to assert for. Asserts for input to be checked by default. This option can't be used when
+ // “[object Object]” is set to true.
+ Checked *bool `json:"checked"`
+ // Asserts that the element is in the indeterminate (mixed) state. Only supported for checkboxes and radio buttons.
+ // This option can't be true when “[object Object]” is provided.
+ Indeterminate *bool `json:"indeterminate"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeDisabledOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeEditableOptions struct {
+ Editable *bool `json:"editable"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeEmptyOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeEnabledOptions struct {
+ Enabled *bool `json:"enabled"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeFocusedOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeHiddenOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeInViewportOptions struct {
+ // The minimal ratio of the element to intersect viewport. If equals to `0`, then element should intersect viewport at
+ // any positive ratio. Defaults to `0`.
+ Ratio *float64 `json:"ratio"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeVisibleOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+ Visible *bool `json:"visible"`
+}
+
+type LocatorAssertionsToContainClassOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToContainTextOptions struct {
+ // Whether to perform case-insensitive match. “[object Object]” option takes precedence over the corresponding regular
+ // expression flag if specified.
+ IgnoreCase *bool `json:"ignoreCase"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+ // Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text.
+ UseInnerText *bool `json:"useInnerText"`
+}
+
+type LocatorAssertionsToHaveAccessibleDescriptionOptions struct {
+ // Whether to perform case-insensitive match. “[object Object]” option takes precedence over the corresponding regular
+ // expression flag if specified.
+ IgnoreCase *bool `json:"ignoreCase"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveAccessibleErrorMessageOptions struct {
+ // Whether to perform case-insensitive match. “[object Object]” option takes precedence over the corresponding regular
+ // expression flag if specified.
+ IgnoreCase *bool `json:"ignoreCase"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveAccessibleNameOptions struct {
+ // Whether to perform case-insensitive match. “[object Object]” option takes precedence over the corresponding regular
+ // expression flag if specified.
+ IgnoreCase *bool `json:"ignoreCase"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveAttributeOptions struct {
+ // Whether to perform case-insensitive match. “[object Object]” option takes precedence over the corresponding regular
+ // expression flag if specified.
+ IgnoreCase *bool `json:"ignoreCase"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveClassOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveCountOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveCSSOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveIdOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveJSPropertyOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveRoleOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveTextOptions struct {
+ // Whether to perform case-insensitive match. “[object Object]” option takes precedence over the corresponding regular
+ // expression flag if specified.
+ IgnoreCase *bool `json:"ignoreCase"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+ // Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text.
+ UseInnerText *bool `json:"useInnerText"`
+}
+
+type LocatorAssertionsToHaveValueOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveValuesOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToMatchAriaSnapshotOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type MouseClickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // defaults to 1. See [UIEvent.Detail].
+ ClickCount *int `json:"clickCount"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+}
+
+type MouseDblclickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+}
+
+type MouseDownOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // defaults to 1. See [UIEvent.Detail].
+ ClickCount *int `json:"clickCount"`
+}
+
+type MouseMoveOptions struct {
+ // Defaults to 1. Sends intermediate `mousemove` events.
+ Steps *int `json:"steps"`
+}
+
+type MouseUpOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // defaults to 1. See [UIEvent.Detail].
+ ClickCount *int `json:"clickCount"`
+}
+
+type PageAddScriptTagOptions struct {
+ // Raw JavaScript content to be injected into frame.
+ Content *string `json:"content"`
+ // Path to the JavaScript file to be injected into frame. If `path` is a relative path, then it is resolved relative
+ // to the current working directory.
+ Path *string `json:"path"`
+ // Script type. Use 'module' in order to load a JavaScript ES6 module. See
+ // [script] for more details.
+ //
+ // [script]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script
+ Type *string `json:"type"`
+ // URL of a script to be added.
+ URL *string `json:"url"`
+}
+
+type PageAddStyleTagOptions struct {
+ // Raw CSS content to be injected into frame.
+ Content *string `json:"content"`
+ // Path to the CSS file to be injected into frame. If `path` is a relative path, then it is resolved relative to the
+ // current working directory.
+ Path *string `json:"path"`
+ // URL of the `<link>` tag.
+ URL *string `json:"url"`
+}
+
+type PageCheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageClickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // defaults to 1. See [UIEvent.Detail].
+ ClickCount *int `json:"clickCount"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageCloseOptions struct {
+ // The reason to be reported to the operations interrupted by the page closure.
+ Reason *string `json:"reason"`
+ // Defaults to `false`. Whether to run the
+ // [before unload] page handlers.
+ //
+ // [before unload]: https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload
+ RunBeforeUnload *bool `json:"runBeforeUnload"`
+}
+
+type PageDblclickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageDispatchEventOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageDragAndDropOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Clicks on the source element at this point relative to the top-left corner of the element's padding box. If not
+ // specified, some visible point of the element is used.
+ SourcePosition *Position `json:"sourcePosition"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Drops on the target element at this point relative to the top-left corner of the element's padding box. If not
+ // specified, some visible point of the element is used.
+ TargetPosition *Position `json:"targetPosition"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageEmulateMediaOptions struct {
+ // Emulates [prefers-colors-scheme]
+ // media feature, supported values are `light` and `dark`. Passing `no-override` disables color scheme
+ // emulation. `no-preference` is deprecated.
+ //
+ // [prefers-colors-scheme]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
+ ColorScheme *ColorScheme `json:"colorScheme"`
+ // Emulates `prefers-contrast` media feature, supported values are `no-preference`, `more`. Passing
+ // `no-override` disables contrast emulation.
+ Contrast *Contrast `json:"contrast"`
+ // Emulates `forced-colors` media feature, supported values are `active` and `none`. Passing `no-override`
+ // disables forced colors emulation.
+ ForcedColors *ForcedColors `json:"forcedColors"`
+ // Changes the CSS media type of the page. The only allowed values are `screen`, `print` and `no-override`.
+ // Passing `no-override` disables CSS media emulation.
+ Media *Media `json:"media"`
+ // Emulates `prefers-reduced-motion` media feature, supported values are `reduce`, `no-preference`. Passing
+ // `no-override` disables reduced motion emulation.
+ ReducedMotion *ReducedMotion `json:"reducedMotion"`
+}
+
+type PageEvalOnSelectorOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+}
+
+type PageFillOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageFocusOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageFrameOptions struct {
+ // Frame name specified in the `iframe`'s `name` attribute. Optional.
+ Name *string `json:"name"`
+ // A glob pattern, regex pattern or predicate receiving frame's `url` as a [URL] object. Optional.
+ URL interface{} `json:"url"`
+}
+
+type PageGetAttributeOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageGetByAltTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type PageGetByLabelOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type PageGetByPlaceholderOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type PageGetByRoleOptions struct {
+ // An attribute that is usually set by `aria-checked` or native `<input type=checkbox>` controls.
+ // Learn more about [`aria-checked`].
+ //
+ // [`aria-checked`]: https://www.w3.org/TR/wai-aria-1.2/#aria-checked
+ Checked *bool `json:"checked"`
+ // An attribute that is usually set by `aria-disabled` or `disabled`.
+ // **NOTE** Unlike most other attributes, `disabled` is inherited through the DOM hierarchy. Learn more about
+ // [`aria-disabled`].
+ //
+ // [`aria-disabled`]: https://www.w3.org/TR/wai-aria-1.2/#aria-disabled
+ Disabled *bool `json:"disabled"`
+ // Whether “[object Object]” is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when
+ // “[object Object]” is a regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+ // An attribute that is usually set by `aria-expanded`.
+ // Learn more about [`aria-expanded`].
+ //
+ // [`aria-expanded`]: https://www.w3.org/TR/wai-aria-1.2/#aria-expanded
+ Expanded *bool `json:"expanded"`
+ // Option that controls whether hidden elements are matched. By default, only non-hidden elements, as
+ // [defined by ARIA], are matched by role selector.
+ // Learn more about [`aria-hidden`].
+ //
+ // [defined by ARIA]: https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion
+ // [`aria-hidden`]: https://www.w3.org/TR/wai-aria-1.2/#aria-hidden
+ IncludeHidden *bool `json:"includeHidden"`
+ // A number attribute that is usually present for roles `heading`, `listitem`, `row`, `treeitem`, with default values
+ // for `<h1>-<h6>` elements.
+ // Learn more about [`aria-level`].
+ //
+ // [`aria-level`]: https://www.w3.org/TR/wai-aria-1.2/#aria-level
+ Level *int `json:"level"`
+ // Option to match the [accessible name]. By default, matching is
+ // case-insensitive and searches for a substring, use “[object Object]” to control this behavior.
+ // Learn more about [accessible name].
+ //
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ Name interface{} `json:"name"`
+ // An attribute that is usually set by `aria-pressed`.
+ // Learn more about [`aria-pressed`].
+ //
+ // [`aria-pressed`]: https://www.w3.org/TR/wai-aria-1.2/#aria-pressed
+ Pressed *bool `json:"pressed"`
+ // An attribute that is usually set by `aria-selected`.
+ // Learn more about [`aria-selected`].
+ //
+ // [`aria-selected`]: https://www.w3.org/TR/wai-aria-1.2/#aria-selected
+ Selected *bool `json:"selected"`
+}
+
+type PageGetByTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type PageGetByTitleOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type PageGoBackOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type PageGoForwardOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type PageGotoOptions struct {
+ // Referer header value. If provided it will take preference over the referer header value set by
+ // [Page.SetExtraHTTPHeaders].
+ Referer *string `json:"referer"`
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type PageHoverOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageInnerHTMLOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageInnerTextOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageInputValueOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageIsCheckedOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageIsDisabledOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageIsEditableOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageIsEnabledOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageIsHiddenOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ //
+ // Deprecated: This option is ignored. [Page.IsHidden] does not wait for the element to become hidden and returns immediately.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageIsVisibleOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ //
+ // Deprecated: This option is ignored. [Page.IsVisible] does not wait for the element to become visible and returns immediately.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageLocatorOptions struct {
+ // Narrows down the results of the method to those which contain elements matching this relative locator. For example,
+ // `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.
+ // Inner locator **must be relative** to the outer locator and is queried starting with the outer locator match, not
+ // the document root. For example, you can find `content` that has `div` in
+ // `<article><content><div>Playwright</div></content></article>`. However, looking for `content` that has `article
+ // div` will fail, because the inner locator must be relative and should not use any elements outside the `content`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ Has Locator `json:"has"`
+ // Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
+ // outer one. For example, `article` that does not have `div` matches `<article><span>Playwright</span></article>`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ HasNot Locator `json:"hasNot"`
+ // Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element.
+ // When passed a [string], matching is case-insensitive and searches for a substring.
+ HasNotText interface{} `json:"hasNotText"`
+ // Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When
+ // passed a [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
+ // `<article><div>Playwright</div></article>`.
+ HasText interface{} `json:"hasText"`
+}
+
+type PagePdfOptions struct {
+ // Display header and footer. Defaults to `false`.
+ DisplayHeaderFooter *bool `json:"displayHeaderFooter"`
+ // HTML template for the print footer. Should use the same format as the “[object Object]”.
+ FooterTemplate *string `json:"footerTemplate"`
+ // Paper format. If set, takes priority over “[object Object]” or “[object Object]” options. Defaults to 'Letter'.
+ Format *string `json:"format"`
+ // HTML template for the print header. Should be valid HTML markup with following classes used to inject printing
+ // values into them:
+ // - `date` formatted print date
+ // - `title` document title
+ // - `url` document location
+ // - `pageNumber` current page number
+ // - `totalPages` total pages in the document
+ HeaderTemplate *string `json:"headerTemplate"`
+ // Paper height, accepts values labeled with units.
+ Height *string `json:"height"`
+ // Paper orientation. Defaults to `false`.
+ Landscape *bool `json:"landscape"`
+ // Paper margins, defaults to none.
+ Margin *Margin `json:"margin"`
+ // Whether or not to embed the document outline into the PDF. Defaults to `false`.
+ Outline *bool `json:"outline"`
+ // Paper ranges to print, e.g., '1-5, 8, 11-13'. Defaults to the empty string, which means print all pages.
+ PageRanges *string `json:"pageRanges"`
+ // The file path to save the PDF to. If “[object Object]” is a relative path, then it is resolved relative to the
+ // current working directory. If no path is provided, the PDF won't be saved to the disk.
+ Path *string `json:"path"`
+ // Give any CSS `@page` size declared in the page priority over what is declared in “[object Object]” and
+ // “[object Object]” or “[object Object]” options. Defaults to `false`, which will scale the content to fit the paper
+ // size.
+ PreferCSSPageSize *bool `json:"preferCSSPageSize"`
+ // Print background graphics. Defaults to `false`.
+ PrintBackground *bool `json:"printBackground"`
+ // Scale of the webpage rendering. Defaults to `1`. Scale amount must be between 0.1 and 2.
+ Scale *float64 `json:"scale"`
+ // Whether or not to generate tagged (accessible) PDF. Defaults to `false`.
+ Tagged *bool `json:"tagged"`
+ // Paper width, accepts values labeled with units.
+ Width *string `json:"width"`
+}
+
+type PagePressOptions struct {
+ // Time to wait between `keydown` and `keyup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageQuerySelectorOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+}
+
+type PageAddLocatorHandlerOptions struct {
+ // By default, after calling the handler Playwright will wait until the overlay becomes hidden, and only then
+ // Playwright will continue with the action/assertion that triggered the handler. This option allows to opt-out of
+ // this behavior, so that overlay can stay visible after the handler has run.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Specifies the maximum number of times this handler should be called. Unlimited by default.
+ Times *int `json:"times"`
+}
+
+type PageReloadOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type PageRouteFromHAROptions struct {
+ // - If set to 'abort' any request not found in the HAR file will be aborted.
+ // - If set to 'fallback' missing requests will be sent to the network.
+ // Defaults to abort.
+ NotFound *HarNotFound `json:"notFound"`
+ // If specified, updates the given HAR with the actual network information instead of serving from file. The file is
+ // written to disk when [BrowserContext.Close] is called.
+ Update *bool `json:"update"`
+ // Optional setting to control resource content management. If `attach` is specified, resources are persisted as
+ // separate files or entries in the ZIP archive. If `embed` is specified, content is stored inline the HAR file.
+ UpdateContent *RouteFromHarUpdateContentPolicy `json:"updateContent"`
+ // When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page,
+ // cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to
+ // `minimal`.
+ UpdateMode *HarMode `json:"updateMode"`
+ // A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the
+ // pattern will be served from the HAR file. If not specified, all requests are served from the HAR file.
+ URL interface{} `json:"url"`
+}
+
+type PageScreenshotOptions struct {
+ // When set to `"disabled"`, stops CSS animations, CSS transitions and Web Animations. Animations get different
+ // treatment depending on their duration:
+ // - finite animations are fast-forwarded to completion, so they'll fire `transitionend` event.
+ // - infinite animations are canceled to initial state, and then played over after the screenshot.
+ // Defaults to `"allow"` that leaves animations untouched.
+ Animations *ScreenshotAnimations `json:"animations"`
+ // When set to `"hide"`, screenshot will hide text caret. When set to `"initial"`, text caret behavior will not be
+ // changed. Defaults to `"hide"`.
+ Caret *ScreenshotCaret `json:"caret"`
+ // An object which specifies clipping of the resulting image.
+ Clip *Rect `json:"clip"`
+ // When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Defaults to
+ // `false`.
+ FullPage *bool `json:"fullPage"`
+ // Specify locators that should be masked when the screenshot is taken. Masked elements will be overlaid with a pink
+ // box `#FF00FF` (customized by “[object Object]”) that completely covers its bounding box. The mask is also applied
+ // to invisible elements, see [Matching only visible elements] to
+ // disable that.
+ //
+ // [Matching only visible elements]: https://playwright.dev/docs/locators#matching-only-visible-elements
+ Mask []Locator `json:"mask"`
+ // Specify the color of the overlay box for masked elements, in
+ // [CSS color format]. Default color is pink `#FF00FF`.
+ //
+ // [CSS color format]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
+ MaskColor *string `json:"maskColor"`
+ // Hides default white background and allows capturing screenshots with transparency. Not applicable to `jpeg` images.
+ // Defaults to `false`.
+ OmitBackground *bool `json:"omitBackground"`
+ // The file path to save the image to. The screenshot type will be inferred from file extension. If “[object Object]”
+ // is a relative path, then it is resolved relative to the current working directory. If no path is provided, the
+ // image won't be saved to the disk.
+ Path *string `json:"path"`
+ // The quality of the image, between 0-100. Not applicable to `png` images.
+ Quality *int `json:"quality"`
+ // When set to `"css"`, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this
+ // will keep screenshots small. Using `"device"` option will produce a single pixel per each device pixel, so
+ // screenshots of high-dpi devices will be twice as large or even larger.
+ // Defaults to `"device"`.
+ Scale *ScreenshotScale `json:"scale"`
+ // Text of the stylesheet to apply while making the screenshot. This is where you can hide dynamic elements, make
+ // elements invisible or change their properties to help you creating repeatable screenshots. This stylesheet pierces
+ // the Shadow DOM and applies to the inner frames.
+ Style *string `json:"style"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // Specify screenshot type, defaults to `png`.
+ Type *ScreenshotType `json:"type"`
+}
+
+type PageSelectOptionOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageSetCheckedOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageSetContentOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type PageSetInputFilesOptions struct {
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageTapOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageTextContentOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageTypeOptions struct {
+ // Time to wait between key presses in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageUncheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageUnrouteAllOptions struct {
+ // Specifies whether to wait for already running handlers and what to do if they throw errors:
+ // - `default` - do not wait for current handler calls (if any) to finish, if unrouted handler throws, it may
+ // result in unhandled error
+ // - `wait` - wait for current handler calls (if any) to finish
+ // - `ignoreErrors` - do not wait for current handler calls (if any) to finish, all errors thrown by the handlers
+ // after unrouting are silently caught
+ Behavior *UnrouteBehavior `json:"behavior"`
+}
+
+type Size struct {
+ // page width in pixels.
+ Width int `json:"width"`
+ // page height in pixels.
+ Height int `json:"height"`
+}
+
+type PageExpectConsoleMessageOptions struct {
+ // Receives the [ConsoleMessage] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(ConsoleMessage) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectDownloadOptions struct {
+ // Receives the [Download] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(Download) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectEventOptions struct {
+ // Receives the event data and resolves to truthy value when the waiting should resolve.
+ Predicate interface{} `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectFileChooserOptions struct {
+ // Receives the [FileChooser] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(FileChooser) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageWaitForFunctionOptions struct {
+ // If “[object Object]” is `raf`, then “[object Object]” is constantly executed in `requestAnimationFrame` callback.
+ // If “[object Object]” is a number, then it is treated as an interval in milliseconds at which the function would be
+ // executed. Defaults to `raf`.
+ Polling interface{} `json:"polling"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageWaitForLoadStateOptions struct {
+ // Optional load state to wait for, defaults to `load`. If the state has been already reached while loading current
+ // document, the method resolves immediately. Can be one of:
+ // - `load` - wait for the `load` event to be fired.
+ // - `domcontentloaded` - wait for the `DOMContentLoaded` event to be fired.
+ // - `networkidle` - **DISCOURAGED** wait until there are no network connections for at least `500` ms. Don't use
+ // this method for testing, rely on web assertions to assess readiness instead.
+ State *LoadState `json:"state"`
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectNavigationOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if
+ // the parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly
+ // equal to the string.
+ URL interface{} `json:"url"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type PageExpectPopupOptions struct {
+ // Receives the [Page] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(Page) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectRequestOptions struct {
+ // Maximum wait time in milliseconds, defaults to 30 seconds, pass `0` to disable the timeout. The default value can
+ // be changed by using the [Page.SetDefaultTimeout] method.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectRequestFinishedOptions struct {
+ // Receives the [Request] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(Request) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectResponseOptions struct {
+ // Maximum wait time in milliseconds, defaults to 30 seconds, pass `0` to disable the timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageWaitForSelectorOptions struct {
+ // Defaults to `visible`. Can be either:
+ // - `attached` - wait for element to be present in DOM.
+ // - `detached` - wait for element to not be present in DOM.
+ // - `visible` - wait for element to have non-empty bounding box and no `visibility:hidden`. Note that element
+ // without any content or with `display:none` has an empty bounding box and is not considered visible.
+ // - `hidden` - wait for element to be either detached from DOM, or have an empty bounding box or
+ // `visibility:hidden`. This is opposite to the `visible` option.
+ State *WaitForSelectorState `json:"state"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageWaitForURLOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type PageExpectWebSocketOptions struct {
+ // Receives the [WebSocket] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(WebSocket) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectWorkerOptions struct {
+ // Receives the [Worker] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(Worker) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageWaitForEventOptions struct {
+ // Receives the event data and resolves to truthy value when the waiting should resolve.
+ Predicate interface{} `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageAssertionsToHaveTitleOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageAssertionsToHaveURLOptions struct {
+ // Whether to perform case-insensitive match. “[object Object]” option takes precedence over the corresponding regular
+ // expression parameter if specified. A provided predicate ignores this flag.
+ IgnoreCase *bool `json:"ignoreCase"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type RequestSizesResult struct {
+ // Size of the request body (POST data payload) in bytes. Set to 0 if there was no body.
+ RequestBodySize int `json:"requestBodySize"`
+ // Total number of bytes from the start of the HTTP request message until (and including) the double CRLF before the
+ // body.
+ RequestHeadersSize int `json:"requestHeadersSize"`
+ // Size of the received response body (encoded) in bytes.
+ ResponseBodySize int `json:"responseBodySize"`
+ // Total number of bytes from the start of the HTTP response message until (and including) the double CRLF before the
+ // body.
+ ResponseHeadersSize int `json:"responseHeadersSize"`
+}
+
+type RequestTiming struct {
+ // Request start time in milliseconds elapsed since January 1, 1970 00:00:00 UTC
+ StartTime float64 `json:"startTime"`
+ // Time immediately before the browser starts the domain name lookup for the resource. The value is given in
+ // milliseconds relative to `startTime`, -1 if not available.
+ DomainLookupStart float64 `json:"domainLookupStart"`
+ // Time immediately after the browser starts the domain name lookup for the resource. The value is given in
+ // milliseconds relative to `startTime`, -1 if not available.
+ DomainLookupEnd float64 `json:"domainLookupEnd"`
+ // Time immediately before the user agent starts establishing the connection to the server to retrieve the resource.
+ // The value is given in milliseconds relative to `startTime`, -1 if not available.
+ ConnectStart float64 `json:"connectStart"`
+ // Time immediately before the browser starts the handshake process to secure the current connection. The value is
+ // given in milliseconds relative to `startTime`, -1 if not available.
+ SecureConnectionStart float64 `json:"secureConnectionStart"`
+ // Time immediately before the user agent starts establishing the connection to the server to retrieve the resource.
+ // The value is given in milliseconds relative to `startTime`, -1 if not available.
+ ConnectEnd float64 `json:"connectEnd"`
+ // Time immediately before the browser starts requesting the resource from the server, cache, or local resource. The
+ // value is given in milliseconds relative to `startTime`, -1 if not available.
+ RequestStart float64 `json:"requestStart"`
+ // Time immediately after the browser receives the first byte of the response from the server, cache, or local
+ // resource. The value is given in milliseconds relative to `startTime`, -1 if not available.
+ ResponseStart float64 `json:"responseStart"`
+ // Time immediately after the browser receives the last byte of the resource or immediately before the transport
+ // connection is closed, whichever comes first. The value is given in milliseconds relative to `startTime`, -1 if not
+ // available.
+ ResponseEnd float64 `json:"responseEnd"`
+}
+
+type ResponseSecurityDetailsResult struct {
+ // Common Name component of the Issuer field. from the certificate. This should only be used for informational
+ // purposes. Optional.
+ Issuer *string `json:"issuer"`
+ // The specific TLS protocol used. (e.g. `TLS 1.3`). Optional.
+ Protocol *string `json:"protocol"`
+ // Common Name component of the Subject field from the certificate. This should only be used for informational
+ // purposes. Optional.
+ SubjectName *string `json:"subjectName"`
+ // Unix timestamp (in seconds) specifying when this cert becomes valid. Optional.
+ ValidFrom *float64 `json:"validFrom"`
+ // Unix timestamp (in seconds) specifying when this cert becomes invalid. Optional.
+ ValidTo *float64 `json:"validTo"`
+}
+
+type ResponseServerAddrResult struct {
+ // IPv4 or IPV6 address of the server.
+ IpAddress string `json:"ipAddress"`
+ Port int `json:"port"`
+}
+
+type RouteContinueOptions struct {
+ // If set changes the request HTTP headers. Header values will be converted to a string.
+ Headers map[string]string `json:"headers"`
+ // If set changes the request method (e.g. GET or POST).
+ Method *string `json:"method"`
+ // If set changes the post data of request.
+ PostData interface{} `json:"postData"`
+ // If set changes the request URL. New URL must have same protocol as original one.
+ URL *string `json:"url"`
+}
+
+type RouteFallbackOptions struct {
+ // If set changes the request HTTP headers. Header values will be converted to a string.
+ Headers map[string]string `json:"headers"`
+ // If set changes the request method (e.g. GET or POST).
+ Method *string `json:"method"`
+ // If set changes the post data of request.
+ PostData interface{} `json:"postData"`
+ // If set changes the request URL. New URL must have same protocol as original one. Changing the URL won't affect the
+ // route matching, all the routes are matched using the original request URL.
+ URL *string `json:"url"`
+}
+
+type RouteFetchOptions struct {
+ // If set changes the request HTTP headers. Header values will be converted to a string.
+ Headers map[string]string `json:"headers"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // If set changes the request method (e.g. GET or POST).
+ Method *string `json:"method"`
+ // If set changes the post data of request.
+ PostData interface{} `json:"postData"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+ // If set changes the request URL. New URL must have same protocol as original one.
+ URL *string `json:"url"`
+}
+
+type RouteFulfillOptions struct {
+ // Response body.
+ Body interface{} `json:"body"`
+ // If set, equals to setting `Content-Type` response header.
+ ContentType *string `json:"contentType"`
+ // Response headers. Header values will be converted to a string.
+ Headers map[string]string `json:"headers"`
+ // File path to respond with. The content type will be inferred from file extension. If `path` is a relative path,
+ // then it is resolved relative to the current working directory.
+ Path *string `json:"path"`
+ // [APIResponse] to fulfill route's request with. Individual fields of the response (such as headers) can be
+ // overridden using fulfill options.
+ Response APIResponse `json:"response"`
+ // Response status code, defaults to `200`.
+ Status *int `json:"status"`
+}
+
+type SelectorsRegisterOptions struct {
+ // Whether to run this selector engine in isolated JavaScript environment. This environment has access to the same
+ // DOM, but not any JavaScript objects from the frame's scripts. Defaults to `false`. Note that running as a content
+ // script is not guaranteed when this engine is used together with other registered engines.
+ ContentScript *bool `json:"contentScript"`
+}
+
+type TracingStartOptions struct {
+ // If specified, intermediate trace files are going to be saved into the files with the given name prefix inside the
+ // “[object Object]” directory specified in [BrowserType.Launch]. To specify the final trace zip file name, you need
+ // to pass `path` option to [Tracing.Stop] instead.
+ Name *string `json:"name"`
+ // Whether to capture screenshots during tracing. Screenshots are used to build a timeline preview.
+ Screenshots *bool `json:"screenshots"`
+ // If this option is true tracing will
+ // - capture DOM snapshot on every action
+ // - record network activity
+ Snapshots *bool `json:"snapshots"`
+ // Whether to include source files for trace actions.
+ Sources *bool `json:"sources"`
+ // Trace name to be shown in the Trace Viewer.
+ Title *string `json:"title"`
+}
+
+type TracingStartChunkOptions struct {
+ // If specified, intermediate trace files are going to be saved into the files with the given name prefix inside the
+ // “[object Object]” directory specified in [BrowserType.Launch]. To specify the final trace zip file name, you need
+ // to pass `path` option to [Tracing.StopChunk] instead.
+ Name *string `json:"name"`
+ // Trace name to be shown in the Trace Viewer.
+ Title *string `json:"title"`
+}
+
+type TracingGroupOptions struct {
+ // Specifies a custom location for the group to be shown in the trace viewer. Defaults to the location of the
+ // [Tracing.Group] call.
+ Location *TracingGroupOptionsLocation `json:"location"`
+}
+
+type WebSocketExpectEventOptions struct {
+ // Receives the event data and resolves to truthy value when the waiting should resolve.
+ Predicate interface{} `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type WebSocketWaitForEventOptions struct {
+ // Receives the event data and resolves to truthy value when the waiting should resolve.
+ Predicate interface{} `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type WebSocketRouteCloseOptions struct {
+ // Optional [close code].
+ //
+ // [close code]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code
+ Code *int `json:"code"`
+ // Optional [close reason].
+ //
+ // [close reason]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#reason
+ Reason *string `json:"reason"`
+}
+
+type ClientCertificate struct {
+ // Exact origin that the certificate is valid for. Origin includes `https` protocol, a hostname and optionally a port.
+ Origin string `json:"origin"`
+ // Path to the file with the certificate in PEM format.
+ CertPath *string `json:"certPath"`
+ // Direct value of the certificate in PEM format.
+ Cert []byte `json:"cert"`
+ // Path to the file with the private key in PEM format.
+ KeyPath *string `json:"keyPath"`
+ // Direct value of the private key in PEM format.
+ Key []byte `json:"key"`
+ // Path to the PFX or PKCS12 encoded private key and certificate chain.
+ PfxPath *string `json:"pfxPath"`
+ // Direct value of the PFX or PKCS12 encoded private key and certificate chain.
+ Pfx []byte `json:"pfx"`
+ // Passphrase for the private key (PEM or PFX).
+ Passphrase *string `json:"passphrase"`
+}
+
+type HttpCredentials struct {
+ Username string `json:"username"`
+ Password string `json:"password"`
+ // Restrain sending http credentials on specific origin (scheme://host:port).
+ Origin *string `json:"origin"`
+ // This option only applies to the requests sent from corresponding [APIRequestContext] and does not affect requests
+ // sent from the browser. `always` - `Authorization` header with basic authentication credentials will be sent with
+ // the each API request. `'unauthorized` - the credentials are only sent when 401 (Unauthorized) response with
+ // `WWW-Authenticate` header is received. Defaults to `unauthorized`.
+ Send *HttpCredentialsSend `json:"send"`
+}
+
+type Proxy struct {
+ // Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example `http://myproxy.com:3128` or
+ // `socks5://myproxy.com:3128`. Short form `myproxy.com:3128` is considered an HTTP proxy.
+ Server string `json:"server"`
+ // Optional comma-separated domains to bypass proxy, for example `".com, chromium.org, .domain.com"`.
+ Bypass *string `json:"bypass"`
+ // Optional username to use if HTTP proxy requires authentication.
+ Username *string `json:"username"`
+ // Optional password to use if HTTP proxy requires authentication.
+ Password *string `json:"password"`
+}
+
+type Origin struct {
+ Origin string `json:"origin"`
+ LocalStorage []NameValue `json:"localStorage"`
+}
+
+type RecordVideo struct {
+ // Path to the directory to put videos into.
+ Dir string `json:"dir"`
+ // Optional dimensions of the recorded videos. If not specified the size will be equal to `viewport` scaled down to
+ // fit into 800x800. If `viewport` is not configured explicitly the video size defaults to 800x450. Actual picture of
+ // each page will be scaled down if necessary to fit the specified size.
+ Size *Size `json:"size"`
+}
+
+type OptionalStorageState struct {
+ // Cookies to set for context
+ Cookies []OptionalCookie `json:"cookies"`
+ // localStorage to set for context
+ Origins []Origin `json:"origins"`
+}
+
+type Position struct {
+ X float64 `json:"x"`
+ Y float64 `json:"y"`
+}
+
+type Margin struct {
+ // Top margin, accepts values labeled with units. Defaults to `0`.
+ Top *string `json:"top"`
+ // Right margin, accepts values labeled with units. Defaults to `0`.
+ Right *string `json:"right"`
+ // Bottom margin, accepts values labeled with units. Defaults to `0`.
+ Bottom *string `json:"bottom"`
+ // Left margin, accepts values labeled with units. Defaults to `0`.
+ Left *string `json:"left"`
+}
+
+type TracingGroupOptionsLocation struct {
+ File string `json:"file"`
+ Line *int `json:"line"`
+ Column *int `json:"column"`
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/glob.go b/vendor/github.com/playwright-community/playwright-go/glob.go
new file mode 100644
index 0000000..77deba3
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/glob.go
@@ -0,0 +1,170 @@
+package playwright
+
+import (
+ "net/url"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var escapedChars = map[rune]bool{
+ '$': true,
+ '^': true,
+ '+': true,
+ '.': true,
+ '*': true,
+ '(': true,
+ ')': true,
+ '|': true,
+ '\\': true,
+ '?': true,
+ '{': true,
+ '}': true,
+ '[': true,
+ ']': true,
+}
+
+func globMustToRegex(glob string) *regexp.Regexp {
+ tokens := []string{"^"}
+ inGroup := false
+
+ for i := 0; i < len(glob); i++ {
+ c := rune(glob[i])
+ if c == '\\' && i+1 < len(glob) {
+ char := rune(glob[i+1])
+ if _, ok := escapedChars[char]; ok {
+ tokens = append(tokens, "\\"+string(char))
+ } else {
+ tokens = append(tokens, string(char))
+ }
+ i++
+ } else if c == '*' {
+ beforeDeep := rune(0)
+ if i > 0 {
+ beforeDeep = rune(glob[i-1])
+ }
+ starCount := 1
+ for i+1 < len(glob) && glob[i+1] == '*' {
+ starCount++
+ i++
+ }
+ afterDeep := rune(0)
+ if i+1 < len(glob) {
+ afterDeep = rune(glob[i+1])
+ }
+ isDeep := starCount > 1 && (beforeDeep == '/' || beforeDeep == 0) && (afterDeep == '/' || afterDeep == 0)
+ if isDeep {
+ tokens = append(tokens, "((?:[^/]*(?:/|$))*)")
+ i++
+ } else {
+ tokens = append(tokens, "([^/]*)")
+ }
+ } else {
+ switch c {
+ case '{':
+ inGroup = true
+ tokens = append(tokens, "(")
+ case '}':
+ inGroup = false
+ tokens = append(tokens, ")")
+ case ',':
+ if inGroup {
+ tokens = append(tokens, "|")
+ } else {
+ tokens = append(tokens, "\\"+string(c))
+ }
+ default:
+ if _, ok := escapedChars[c]; ok {
+ tokens = append(tokens, "\\"+string(c))
+ } else {
+ tokens = append(tokens, string(c))
+ }
+ }
+ }
+ }
+
+ tokens = append(tokens, "$")
+ return regexp.MustCompile(strings.Join(tokens, ""))
+}
+
+func resolveGlobToRegex(baseURL *string, glob string, isWebSocketUrl bool) *regexp.Regexp {
+ if isWebSocketUrl {
+ baseURL = toWebSocketBaseURL(baseURL)
+ }
+ glob = resolveGlobBase(baseURL, glob)
+ return globMustToRegex(glob)
+}
+
+func resolveGlobBase(baseURL *string, match string) string {
+ if strings.HasPrefix(match, "*") {
+ return match
+ }
+
+ tokenMap := make(map[string]string)
+ mapToken := func(original string, replacement string) string {
+ if len(original) == 0 {
+ return ""
+ }
+ tokenMap[replacement] = original
+ return replacement
+ }
+ // Escaped `\\?` behaves the same as `?` in our glob patterns.
+ match = strings.ReplaceAll(match, `\\?`, "?")
+ // Glob symbols may be escaped in the URL and some of them such as ? affect resolution,
+ // so we replace them with safe components first.
+ relativePath := strings.Split(match, "/")
+ for i, token := range relativePath {
+ if token == "." || token == ".." || token == "" {
+ continue
+ }
+ // Handle special case of http*://, note that the new schema has to be
+ // a web schema so that slashes are properly inserted after domain.
+ if i == 0 && strings.HasSuffix(token, ":") {
+ relativePath[i] = mapToken(token, "http:")
+ } else {
+ questionIndex := strings.Index(token, "?")
+ if questionIndex == -1 {
+ relativePath[i] = mapToken(token, "$_"+strconv.Itoa(i)+"_$")
+ } else {
+ newPrefix := mapToken(token[:questionIndex], "$_"+strconv.Itoa(i)+"_$")
+ newSuffix := mapToken(token[questionIndex:], "?$"+strconv.Itoa(i)+"_$")
+ relativePath[i] = newPrefix + newSuffix
+ }
+ }
+ }
+ resolved := constructURLBasedOnBaseURL(baseURL, strings.Join(relativePath, "/"))
+ for token, original := range tokenMap {
+ resolved = strings.ReplaceAll(resolved, token, original)
+ }
+ return resolved
+}
+
+func constructURLBasedOnBaseURL(baseURL *string, givenURL string) string {
+ u, err := url.Parse(givenURL)
+ if err != nil {
+ return givenURL
+ }
+ if baseURL != nil {
+ base, err := url.Parse(*baseURL)
+ if err != nil {
+ return givenURL
+ }
+ u = base.ResolveReference(u)
+ }
+ if u.Path == "" { // In Node.js, new URL('http://localhost') returns 'http://localhost/'.
+ u.Path = "/"
+ }
+ return u.String()
+}
+
+func toWebSocketBaseURL(baseURL *string) *string {
+ if baseURL == nil {
+ return nil
+ }
+
+ // Allow http(s) baseURL to match ws(s) urls.
+ re := regexp.MustCompile(`(?m)^http(s?://)`)
+ wsBaseURL := re.ReplaceAllString(*baseURL, "ws$1")
+
+ return &wsBaseURL
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/har_router.go b/vendor/github.com/playwright-community/playwright-go/har_router.go
new file mode 100644
index 0000000..0c95d53
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/har_router.go
@@ -0,0 +1,110 @@
+package playwright
+
+import (
+ "errors"
+)
+
+type harRouter struct {
+ localUtils *localUtilsImpl
+ harId string
+ notFoundAction HarNotFound
+ urlOrPredicate interface{}
+ err error
+}
+
+func (r *harRouter) addContextRoute(context BrowserContext) error {
+ if r.err != nil {
+ return r.err
+ }
+ err := context.Route(r.urlOrPredicate, func(route Route) {
+ err := r.handle(route)
+ if err != nil {
+ logger.Error("Error handling context route", "error", err)
+ }
+ })
+ if err != nil {
+ return err
+ }
+ return r.err
+}
+
+func (r *harRouter) addPageRoute(page Page) error {
+ if r.err != nil {
+ return r.err
+ }
+ err := page.Route(r.urlOrPredicate, func(route Route) {
+ err := r.handle(route)
+ if err != nil {
+ logger.Error("Error handling page route", "error", err)
+ }
+ })
+ if err != nil {
+ return err
+ }
+ return r.err
+}
+
+func (r *harRouter) dispose() {
+ go r.localUtils.HarClose(r.harId)
+}
+
+func (r *harRouter) handle(route Route) error {
+ if r.err != nil {
+ return r.err
+ }
+ request := route.Request()
+ postData, err := request.PostDataBuffer()
+ if err != nil {
+ return err
+ }
+ response, err := r.localUtils.HarLookup(harLookupOptions{
+ HarId: r.harId,
+ URL: request.URL(),
+ Method: request.Method(),
+ Headers: request.Headers(),
+ IsNavigationRequest: request.IsNavigationRequest(),
+ PostData: postData,
+ })
+ if err != nil {
+ return err
+ }
+ switch response.Action {
+ case "redirect":
+ if response.RedirectURL == nil {
+ return errors.New("redirect url is null")
+ }
+ return route.(*routeImpl).redirectedNavigationRequest(*response.RedirectURL)
+ case "fulfill":
+ if response.Body == nil {
+ return errors.New("fulfill body is null")
+ }
+ return route.Fulfill(RouteFulfillOptions{
+ Body: *response.Body,
+ Status: response.Status,
+ Headers: deserializeNameAndValueToMap(response.Headers),
+ })
+ case "error":
+ logger.Error("har action error", "error", *response.Message)
+ fallthrough
+ case "noentry":
+ }
+ if r.notFoundAction == *HarNotFoundAbort {
+ return route.Abort()
+ }
+ return route.Fallback()
+}
+
+func newHarRouter(localUtils *localUtilsImpl, file string, notFoundAction HarNotFound, urlOrPredicate interface{}) *harRouter {
+ harId, err := localUtils.HarOpen(file)
+ var url interface{} = "**/*"
+ if urlOrPredicate != nil {
+ url = urlOrPredicate
+ }
+ return &harRouter{
+ localUtils: localUtils,
+ harId: harId,
+ notFoundAction: notFoundAction,
+ urlOrPredicate: url,
+ err: err,
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/helpers.go b/vendor/github.com/playwright-community/playwright-go/helpers.go
new file mode 100644
index 0000000..b2244f1
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/helpers.go
@@ -0,0 +1,628 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "regexp"
+ "strings"
+ "sync"
+ "sync/atomic"
+
+ mapset "github.com/deckarep/golang-set/v2"
+)
+
+type (
+ routeHandler = func(Route)
+)
+
+func skipFieldSerialization(val reflect.Value) bool {
+ typ := val.Type()
+ return (typ.Kind() == reflect.Ptr ||
+ typ.Kind() == reflect.Interface ||
+ typ.Kind() == reflect.Map ||
+ typ.Kind() == reflect.Slice) && val.IsNil() || (val.Kind() == reflect.Interface && val.Elem().Kind() == reflect.Ptr && val.Elem().IsNil())
+}
+
+func transformStructValues(in interface{}) interface{} {
+ v := reflect.ValueOf(in)
+ if v.Kind() == reflect.Ptr {
+ v = v.Elem()
+ }
+ if _, ok := in.(*channel); ok {
+ return in
+ }
+ if v.Kind() == reflect.Map || v.Kind() == reflect.Struct {
+ return transformStructIntoMapIfNeeded(in)
+ }
+ if v.Kind() == reflect.Slice {
+ outSlice := []interface{}{}
+ for i := 0; i < v.Len(); i++ {
+ if !skipFieldSerialization(v.Index(i)) {
+ outSlice = append(outSlice, transformStructValues(v.Index(i).Interface()))
+ }
+ }
+ return outSlice
+ }
+ if v.Interface() == Null() || (v.Kind() == reflect.String && v.String() == Null().(string)) {
+ return "null"
+ }
+ return in
+}
+
+func transformStructIntoMapIfNeeded(inStruct interface{}) map[string]interface{} {
+ out := make(map[string]interface{})
+ v := reflect.ValueOf(inStruct)
+ if v.Kind() == reflect.Ptr {
+ v = v.Elem()
+ }
+ typ := v.Type()
+ if v.Kind() == reflect.Struct {
+ // Merge into the base map by the JSON struct tag
+ for i := 0; i < v.NumField(); i++ {
+ fi := typ.Field(i)
+ // Skip the values when the field is a pointer (like *string) and nil.
+ if fi.IsExported() && !skipFieldSerialization(v.Field(i)) {
+ // We use the JSON struct fields for getting the original names
+ // out of the field.
+ tagv := fi.Tag.Get("json")
+ key := strings.Split(tagv, ",")[0]
+ if key == "" {
+ key = fi.Name
+ }
+ out[key] = transformStructValues(v.Field(i).Interface())
+ }
+ }
+ } else if v.Kind() == reflect.Map {
+ // Merge into the base map
+ for _, key := range v.MapKeys() {
+ if !skipFieldSerialization(v.MapIndex(key)) {
+ out[key.String()] = transformStructValues(v.MapIndex(key).Interface())
+ }
+ }
+ }
+ return out
+}
+
+// transformOptions handles the parameter data transformation
+func transformOptions(options ...interface{}) map[string]interface{} {
+ var base map[string]interface{}
+ var option interface{}
+ // Case 1: No options are given
+ if len(options) == 0 {
+ return make(map[string]interface{})
+ }
+ if len(options) == 1 {
+ // Case 2: a single value (either struct or map) is given.
+ base = make(map[string]interface{})
+ option = options[0]
+ } else if len(options) == 2 {
+ // Case 3: two values are given. The first one needs to be transformed
+ // to a map, the sencond one will be then get merged into the first
+ // base map.
+ if reflect.ValueOf(options[0]).Kind() != reflect.Map {
+ base = transformOptions(options[0])
+ } else {
+ base = transformStructIntoMapIfNeeded(options[0])
+ }
+ option = options[1]
+ }
+ v := reflect.ValueOf(option)
+ if v.Kind() == reflect.Slice {
+ if v.Len() == 0 {
+ return base
+ }
+ option = v.Index(0).Interface()
+ }
+
+ if option == nil {
+ return base
+ }
+ v = reflect.ValueOf(option)
+
+ if v.Kind() == reflect.Ptr {
+ v = v.Elem()
+ }
+
+ optionMap := transformStructIntoMapIfNeeded(v.Interface())
+ for key, value := range optionMap {
+ base[key] = value
+ }
+ return base
+}
+
+func remapValue(inMapValue reflect.Value, outStructValue reflect.Value) {
+ switch outStructValue.Type().Kind() {
+ case reflect.Bool:
+ outStructValue.SetBool(inMapValue.Bool())
+ case reflect.String:
+ outStructValue.SetString(inMapValue.String())
+ case reflect.Float64:
+ outStructValue.SetFloat(inMapValue.Float())
+ case reflect.Int:
+ outStructValue.SetInt(int64(inMapValue.Float()))
+ case reflect.Slice:
+ outStructValue.Set(reflect.MakeSlice(outStructValue.Type(), inMapValue.Len(), inMapValue.Cap()))
+ for i := 0; i < inMapValue.Len(); i++ {
+ remapValue(inMapValue.Index(i).Elem(), outStructValue.Index(i))
+ }
+ case reflect.Struct:
+ structTyp := outStructValue.Type()
+ for i := 0; i < outStructValue.NumField(); i++ {
+ fi := structTyp.Field(i)
+ key := strings.Split(fi.Tag.Get("json"), ",")[0]
+ structField := outStructValue.Field(i)
+ structFieldDeref := outStructValue.Field(i)
+ if structField.Type().Kind() == reflect.Ptr {
+ structField.Set(reflect.New(structField.Type().Elem()))
+ structFieldDeref = structField.Elem()
+ }
+ for _, e := range inMapValue.MapKeys() {
+ if key == e.String() {
+ value := inMapValue.MapIndex(e)
+ remapValue(value.Elem(), structFieldDeref)
+ }
+ }
+ }
+ default:
+ panic(inMapValue.Interface())
+ }
+}
+
+func remapMapToStruct(inputMap interface{}, outStruct interface{}) {
+ remapValue(reflect.ValueOf(inputMap), reflect.ValueOf(outStruct).Elem())
+}
+
+type urlMatcher struct {
+ raw interface{}
+ pattern *regexp.Regexp
+ matchFn func(url string) bool
+}
+
+func newURLMatcher(urlOrPredicate interface{}, baseURL *string, isWsUrl ...bool) *urlMatcher {
+ switch v := urlOrPredicate.(type) {
+ case *regexp.Regexp:
+ return &urlMatcher{pattern: v, raw: urlOrPredicate}
+ case string:
+ return &urlMatcher{
+ pattern: resolveGlobToRegex(baseURL, v, len(isWsUrl) > 0 && isWsUrl[0]),
+ raw: urlOrPredicate,
+ }
+ }
+ fn, ok := urlOrPredicate.(func(string) bool)
+ if ok {
+ return &urlMatcher{
+ matchFn: fn,
+ raw: urlOrPredicate,
+ }
+ }
+ panic(fmt.Errorf("invalid urlOrPredicate: %v", urlOrPredicate))
+}
+
+func (u *urlMatcher) Matches(url string) bool {
+ if u.matchFn != nil {
+ return u.matchFn(url)
+ }
+ if u.pattern != nil {
+ return u.pattern.MatchString(url)
+ }
+ return false
+}
+
+// SameWith compares String() if urlOrPredicate is *regexp.Regexp
+func (u *urlMatcher) SameWith(urlOrPredicate interface{}) bool {
+ switch v := urlOrPredicate.(type) {
+ case *regexp.Regexp:
+ return u.pattern.String() == v.String()
+ default:
+ return u.raw == urlOrPredicate
+ }
+}
+
+type routeHandlerInvocation struct {
+ route Route
+ complete chan bool
+}
+
+type routeHandlerEntry struct {
+ matcher *urlMatcher
+ handler routeHandler
+ times int
+ count int32
+ ignoreErrors *atomic.Bool
+ activeInvocations mapset.Set[*routeHandlerInvocation]
+}
+
+func (r *routeHandlerEntry) Matches(url string) bool {
+ return r.matcher.Matches(url)
+}
+
+func (r *routeHandlerEntry) Handle(route Route) chan bool {
+ handlerInvocation := &routeHandlerInvocation{
+ route: route,
+ complete: make(chan bool, 1),
+ }
+ r.activeInvocations.Add(handlerInvocation)
+
+ defer func() {
+ handlerInvocation.complete <- true
+ r.activeInvocations.Remove(handlerInvocation)
+ }()
+ defer func() {
+ // If the handler was stopped (without waiting for completion), we ignore all exceptions.
+ if r.ignoreErrors.Load() {
+ _ = recover()
+ route.(*routeImpl).reportHandled(false)
+ } else {
+ e := recover()
+ if e != nil {
+ err, ok := e.(error)
+ if ok && errors.Is(err, ErrTargetClosed) {
+ panic(fmt.Errorf("\"%w\" while running route callback.\nConsider awaiting `page.UnrouteAll(playwright.PageUnrouteAllOptions{Behavior: playwright.UnrouteBehaviorIgnoreErrors})`\nbefore the end of the test to ignore remaining routes in flight.", err))
+ }
+ panic(e)
+ }
+ }
+ }()
+
+ return r.handleInternal(route)
+}
+
+func (r *routeHandlerEntry) Stop(behavior string) {
+ // When a handler is manually unrouted or its page/context is closed we either
+ // - wait for the current handler invocations to finish
+ // - or do not wait, if the user opted out of it, but swallow all exceptions
+ // that happen after the unroute/close.
+ if behavior == string(*UnrouteBehaviorIgnoreErrors) {
+ r.ignoreErrors.Store(true)
+ } else {
+ wg := &sync.WaitGroup{}
+ r.activeInvocations.Each(func(activation *routeHandlerInvocation) bool {
+ if !activation.route.(*routeImpl).didThrow {
+ wg.Add(1)
+ go func(complete chan bool) {
+ <-complete
+ wg.Done()
+ }(activation.complete)
+ }
+ return false
+ })
+ wg.Wait()
+ }
+}
+
+func (r *routeHandlerEntry) handleInternal(route Route) chan bool {
+ handled := route.(*routeImpl).startHandling()
+ atomic.AddInt32(&r.count, 1)
+ r.handler(route)
+ return handled
+}
+
+func (r *routeHandlerEntry) WillExceed() bool {
+ if r.times == 0 {
+ return false
+ }
+ return int(atomic.LoadInt32(&r.count)+1) >= r.times
+}
+
+func newRouteHandlerEntry(matcher *urlMatcher, handler routeHandler, times ...int) *routeHandlerEntry {
+ n := 0
+ if len(times) > 0 {
+ n = times[0]
+ }
+ return &routeHandlerEntry{
+ matcher: matcher,
+ handler: handler,
+ times: n,
+ count: 0,
+ ignoreErrors: &atomic.Bool{},
+ activeInvocations: mapset.NewSet[*routeHandlerInvocation](),
+ }
+}
+
+func prepareInterceptionPatterns(handlers []*routeHandlerEntry) []map[string]interface{} {
+ patterns := []map[string]interface{}{}
+ all := false
+ for _, h := range handlers {
+ switch h.matcher.raw.(type) {
+ case *regexp.Regexp:
+ pattern, flags := convertRegexp(h.matcher.raw.(*regexp.Regexp))
+ patterns = append(patterns, map[string]interface{}{
+ "regexSource": pattern,
+ "regexFlags": flags,
+ })
+ case string:
+ patterns = append(patterns, map[string]interface{}{
+ "glob": h.matcher.raw.(string),
+ })
+ default:
+ all = true
+ }
+ }
+ if all {
+ return []map[string]interface{}{
+ {
+ "glob": "**/*",
+ },
+ }
+ }
+ return patterns
+}
+
+const defaultTimeout = 30 * 1000
+
+type timeoutSettings struct {
+ sync.RWMutex
+ parent *timeoutSettings
+ defaultTimeout *float64
+ defaultNavigationTimeout *float64
+}
+
+func (t *timeoutSettings) SetDefaultTimeout(timeout *float64) {
+ t.Lock()
+ defer t.Unlock()
+ t.defaultTimeout = timeout
+}
+
+func (t *timeoutSettings) DefaultTimeout() *float64 {
+ t.RLock()
+ defer t.RUnlock()
+ return t.defaultTimeout
+}
+
+func (t *timeoutSettings) Timeout(timeout ...float64) float64 {
+ t.RLock()
+ defer t.RUnlock()
+ if len(timeout) == 1 {
+ return timeout[0]
+ }
+ if t.defaultTimeout != nil {
+ return *t.defaultTimeout
+ }
+ if t.parent != nil {
+ return t.parent.Timeout()
+ }
+ return defaultTimeout
+}
+
+func (t *timeoutSettings) DefaultNavigationTimeout() *float64 {
+ t.RLock()
+ defer t.RUnlock()
+ return t.defaultNavigationTimeout
+}
+
+func (t *timeoutSettings) SetDefaultNavigationTimeout(navigationTimeout *float64) {
+ t.Lock()
+ defer t.Unlock()
+ t.defaultNavigationTimeout = navigationTimeout
+}
+
+func (t *timeoutSettings) NavigationTimeout() float64 {
+ t.RLock()
+ defer t.RUnlock()
+ if t.defaultNavigationTimeout != nil {
+ return *t.defaultNavigationTimeout
+ }
+ if t.parent != nil {
+ return t.parent.NavigationTimeout()
+ }
+ return defaultTimeout
+}
+
+func newTimeoutSettings(parent *timeoutSettings) *timeoutSettings {
+ return &timeoutSettings{
+ parent: parent,
+ defaultTimeout: nil,
+ defaultNavigationTimeout: nil,
+ }
+}
+
+// SelectOptionValues is the option struct for ElementHandle.Select() etc.
+type SelectOptionValues struct {
+ ValuesOrLabels *[]string
+ Values *[]string
+ Indexes *[]int
+ Labels *[]string
+ Elements *[]ElementHandle
+}
+
+func convertSelectOptionSet(values SelectOptionValues) map[string]interface{} {
+ out := make(map[string]interface{})
+ if values == (SelectOptionValues{}) {
+ return out
+ }
+
+ var o []map[string]interface{}
+ if values.ValuesOrLabels != nil {
+ for _, v := range *values.ValuesOrLabels {
+ m := map[string]interface{}{"valueOrLabel": v}
+ o = append(o, m)
+ }
+ }
+ if values.Values != nil {
+ for _, v := range *values.Values {
+ m := map[string]interface{}{"value": v}
+ o = append(o, m)
+ }
+ }
+ if values.Indexes != nil {
+ for _, i := range *values.Indexes {
+ m := map[string]interface{}{"index": i}
+ o = append(o, m)
+ }
+ }
+ if values.Labels != nil {
+ for _, l := range *values.Labels {
+ m := map[string]interface{}{"label": l}
+ o = append(o, m)
+ }
+ }
+ if o != nil {
+ out["options"] = o
+ }
+
+ var e []*channel
+ if values.Elements != nil {
+ for _, eh := range *values.Elements {
+ e = append(e, eh.(*elementHandleImpl).channel)
+ }
+ }
+ if e != nil {
+ out["elements"] = e
+ }
+
+ return out
+}
+
+func unroute(inRoutes []*routeHandlerEntry, url interface{}, handlers ...routeHandler) ([]*routeHandlerEntry, []*routeHandlerEntry, error) {
+ var handler routeHandler
+ if len(handlers) == 1 {
+ handler = handlers[0]
+ }
+ handlerPtr := reflect.ValueOf(handler).Pointer()
+
+ removed := make([]*routeHandlerEntry, 0)
+ remaining := make([]*routeHandlerEntry, 0)
+
+ for _, route := range inRoutes {
+ routeHandlerPtr := reflect.ValueOf(route.handler).Pointer()
+ // note: compare regex expression if url is a regexp, not pointer
+ if !route.matcher.SameWith(url) ||
+ (handler != nil && routeHandlerPtr != handlerPtr) {
+ remaining = append(remaining, route)
+ } else {
+ removed = append(removed, route)
+ }
+ }
+
+ return removed, remaining, nil
+}
+
+func serializeMapToNameAndValue(headers map[string]string) []map[string]string {
+ serialized := make([]map[string]string, 0)
+ for name, value := range headers {
+ serialized = append(serialized, map[string]string{
+ "name": name,
+ "value": value,
+ })
+ }
+ return serialized
+}
+
+// assignStructFields assigns fields from src to dest,
+//
+// omitExtra determines whether to omit src's extra fields
+func assignStructFields(dest, src interface{}, omitExtra bool) error {
+ destValue := reflect.ValueOf(dest)
+ if destValue.Kind() != reflect.Ptr || destValue.IsNil() {
+ return fmt.Errorf("dest must be a non-nil pointer")
+ }
+ destValue = destValue.Elem()
+ if destValue.Kind() != reflect.Struct {
+ return fmt.Errorf("dest must be a struct")
+ }
+
+ srcValue := reflect.ValueOf(src)
+ if srcValue.Kind() == reflect.Ptr {
+ srcValue = srcValue.Elem()
+ }
+ if srcValue.Kind() != reflect.Struct {
+ return fmt.Errorf("src must be a struct")
+ }
+
+ for i := 0; i < destValue.NumField(); i++ {
+ destField := destValue.Field(i)
+ destFieldType := destField.Type()
+ destFieldName := destValue.Type().Field(i).Name
+
+ if srcField := srcValue.FieldByName(destFieldName); srcField.IsValid() && srcField.Type() != destFieldType {
+ return fmt.Errorf("mismatched field type for field %s", destFieldName)
+ } else if srcField.IsValid() {
+ destField.Set(srcField)
+ }
+ }
+
+ if !omitExtra {
+ for i := 0; i < srcValue.NumField(); i++ {
+ srcFieldName := srcValue.Type().Field(i).Name
+
+ if destField := destValue.FieldByName(srcFieldName); !destField.IsValid() {
+ return fmt.Errorf("extra field %s in src", srcFieldName)
+ }
+ }
+ }
+
+ return nil
+}
+
+func deserializeNameAndValueToMap(headersArray []map[string]string) map[string]string {
+ unserialized := make(map[string]string)
+ for _, item := range headersArray {
+ unserialized[item["name"]] = item["value"]
+ }
+ return unserialized
+}
+
+type recordHarOptions struct {
+ Path string `json:"path"`
+ Content *HarContentPolicy `json:"content,omitempty"`
+ Mode *HarMode `json:"mode,omitempty"`
+ UrlGlob *string `json:"urlGlob,omitempty"`
+ UrlRegexSource *string `json:"urlRegexSource,omitempty"`
+ UrlRegexFlags *string `json:"urlRegexFlags,omitempty"`
+}
+
+type recordHarInputOptions struct {
+ Path string
+ URL interface{}
+ Mode *HarMode
+ Content *HarContentPolicy
+ OmitContent *bool
+}
+
+type harRecordingMetadata struct {
+ Path string
+ Content *HarContentPolicy
+}
+
+func prepareRecordHarOptions(option recordHarInputOptions) recordHarOptions {
+ out := recordHarOptions{
+ Path: option.Path,
+ }
+ if option.URL != nil {
+ switch option.URL.(type) {
+ case *regexp.Regexp:
+ pattern, flags := convertRegexp(option.URL.(*regexp.Regexp))
+ out.UrlRegexSource = String(pattern)
+ out.UrlRegexFlags = String(flags)
+ case string:
+ out.UrlGlob = String(option.URL.(string))
+ }
+ }
+ if option.Mode != nil {
+ out.Mode = option.Mode
+ }
+ if option.Content != nil {
+ out.Content = option.Content
+ } else if option.OmitContent != nil && *option.OmitContent {
+ out.Content = HarContentPolicyOmit
+ }
+ return out
+}
+
+type safeValue[T any] struct {
+ sync.Mutex
+ v T
+}
+
+func (s *safeValue[T]) Set(v T) {
+ s.Lock()
+ defer s.Unlock()
+ s.v = v
+}
+
+func (s *safeValue[T]) Get() T {
+ s.Lock()
+ defer s.Unlock()
+ return s.v
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/input.go b/vendor/github.com/playwright-community/playwright-go/input.go
new file mode 100644
index 0000000..d6e4ba4
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/input.go
@@ -0,0 +1,117 @@
+package playwright
+
+type mouseImpl struct {
+ channel *channel
+}
+
+func newMouse(channel *channel) *mouseImpl {
+ return &mouseImpl{
+ channel: channel,
+ }
+}
+
+func (m *mouseImpl) Move(x float64, y float64, options ...MouseMoveOptions) error {
+ _, err := m.channel.Send("mouseMove", map[string]interface{}{
+ "x": x,
+ "y": y,
+ }, options)
+ return err
+}
+
+func (m *mouseImpl) Down(options ...MouseDownOptions) error {
+ _, err := m.channel.Send("mouseDown", options)
+ return err
+}
+
+func (m *mouseImpl) Up(options ...MouseUpOptions) error {
+ _, err := m.channel.Send("mouseUp", options)
+ return err
+}
+
+func (m *mouseImpl) Click(x, y float64, options ...MouseClickOptions) error {
+ _, err := m.channel.Send("mouseClick", map[string]interface{}{
+ "x": x,
+ "y": y,
+ }, options)
+ return err
+}
+
+func (m *mouseImpl) Dblclick(x, y float64, options ...MouseDblclickOptions) error {
+ var option MouseDblclickOptions
+ if len(options) == 1 {
+ option = options[0]
+ }
+ return m.Click(x, y, MouseClickOptions{
+ ClickCount: Int(2),
+ Button: option.Button,
+ Delay: option.Delay,
+ })
+}
+
+func (m *mouseImpl) Wheel(deltaX, deltaY float64) error {
+ _, err := m.channel.Send("mouseWheel", map[string]interface{}{
+ "deltaX": deltaX,
+ "deltaY": deltaY,
+ })
+ return err
+}
+
+type keyboardImpl struct {
+ channel *channel
+}
+
+func newKeyboard(channel *channel) *keyboardImpl {
+ return &keyboardImpl{
+ channel: channel,
+ }
+}
+
+func (m *keyboardImpl) Down(key string) error {
+ _, err := m.channel.Send("keyboardDown", map[string]interface{}{
+ "key": key,
+ })
+ return err
+}
+
+func (m *keyboardImpl) Up(key string) error {
+ _, err := m.channel.Send("keyboardUp", map[string]interface{}{
+ "key": key,
+ })
+ return err
+}
+
+func (m *keyboardImpl) InsertText(text string) error {
+ _, err := m.channel.Send("keyboardInsertText", map[string]interface{}{
+ "text": text,
+ })
+ return err
+}
+
+func (m *keyboardImpl) Type(text string, options ...KeyboardTypeOptions) error {
+ _, err := m.channel.Send("keyboardInsertText", map[string]interface{}{
+ "text": text,
+ }, options)
+ return err
+}
+
+func (m *keyboardImpl) Press(key string, options ...KeyboardPressOptions) error {
+ _, err := m.channel.Send("keyboardPress", map[string]interface{}{
+ "key": key,
+ }, options)
+ return err
+}
+
+type touchscreenImpl struct {
+ channel *channel
+}
+
+func newTouchscreen(channel *channel) *touchscreenImpl {
+ return &touchscreenImpl{
+ channel: channel,
+ }
+}
+
+func (t *touchscreenImpl) Tap(x int, y int) error {
+ _, err := t.channel.Send("touchscreenTap", map[string]interface{}{"x": x, "y": y})
+ return err
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/input_files_helper.go b/vendor/github.com/playwright-community/playwright-go/input_files_helper.go
new file mode 100644
index 0000000..3318cb5
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/input_files_helper.go
@@ -0,0 +1,202 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+)
+
+const fileSizeLimitInBytes = 50 * 1024 * 1024
+
+var ErrInputFilesSizeExceeded = errors.New("Cannot set buffer larger than 50Mb, please write it to a file and pass its path instead.")
+
+type inputFiles struct {
+ Selector *string `json:"selector,omitempty"`
+ Streams []*channel `json:"streams,omitempty"` // writableStream
+ LocalPaths []string `json:"localPaths,omitempty"`
+ Payloads []map[string]string `json:"payloads,omitempty"`
+ LocalDirectory *string `json:"localDirectory,omitempty"`
+ DirectoryStream *channel `json:"directoryStream,omitempty"`
+}
+
+type fileItem struct {
+ LastModifiedMs *int64 `json:"lastModifiedMs,omitempty"`
+ Name string `json:"name"`
+}
+
+// convertInputFiles converts files to proper format for Playwright
+//
+// - files should be one of: string, []string, InputFile, []InputFile,
+// string: local file path
+func convertInputFiles(files interface{}, context *browserContextImpl) (*inputFiles, error) {
+ var (
+ converted = &inputFiles{}
+ paths []string
+ )
+ switch items := files.(type) {
+ case InputFile:
+ if sizeOfInputFiles([]InputFile{items}) > fileSizeLimitInBytes {
+ return nil, ErrInputFilesSizeExceeded
+ }
+ converted.Payloads = normalizeFilePayloads([]InputFile{items})
+ case []InputFile:
+ if sizeOfInputFiles(items) > fileSizeLimitInBytes {
+ return nil, ErrInputFilesSizeExceeded
+ }
+ converted.Payloads = normalizeFilePayloads(items)
+ case string: // local file path
+ paths = []string{items}
+ case []string:
+ paths = items
+ default:
+ return nil, errors.New("files should be one of: string, []string, InputFile, []InputFile")
+ }
+
+ localPaths, localDir, err := resolvePathsAndDirectoryForInputFiles(paths)
+ if err != nil {
+ return nil, err
+ }
+
+ if !context.connection.isRemote {
+ converted.LocalPaths = localPaths
+ converted.LocalDirectory = localDir
+ return converted, nil
+ }
+
+ // remote
+ params := map[string]interface{}{
+ "items": []fileItem{},
+ }
+ allFiles := localPaths
+ if localDir != nil {
+ params["rootDirName"] = filepath.Base(*localDir)
+ allFiles, err = listFiles(*localDir)
+ if err != nil {
+ return nil, err
+ }
+ }
+ for _, file := range allFiles {
+ lastModifiedMs, err := getFileLastModifiedMs(file)
+ if err != nil {
+ return nil, fmt.Errorf("failed to get last modified time of %s: %w", file, err)
+ }
+ filename := filepath.Base(file)
+ if localDir != nil {
+ var err error
+ filename, err = filepath.Rel(*localDir, file)
+ if err != nil {
+ return nil, err
+ }
+ }
+ params["items"] = append(params["items"].([]fileItem), fileItem{
+ LastModifiedMs: &lastModifiedMs,
+ Name: filename,
+ })
+ }
+
+ ret, err := context.connection.WrapAPICall(func() (interface{}, error) {
+ return context.channel.SendReturnAsDict("createTempFiles", params)
+ }, true)
+ if err != nil {
+ return nil, err
+ }
+ result := ret.(map[string]interface{})
+
+ streams := make([]*channel, 0)
+ items := result["writableStreams"].([]interface{})
+ for i := 0; i < len(allFiles); i++ {
+ stream := fromChannel(items[i]).(*writableStream)
+ if err := stream.Copy(allFiles[i]); err != nil {
+ return nil, err
+ }
+ streams = append(streams, stream.channel)
+ }
+
+ if result["rootDir"] != nil {
+ converted.DirectoryStream = result["rootDir"].(*channel)
+ } else {
+ converted.Streams = streams
+ }
+
+ return converted, nil
+}
+
+func getFileLastModifiedMs(path string) (int64, error) {
+ info, err := os.Stat(path)
+ if err != nil {
+ return 0, err
+ }
+ if info.IsDir() {
+ return 0, fmt.Errorf("%s is a directory", path)
+ }
+ return info.ModTime().UnixMilli(), nil
+}
+
+func sizeOfInputFiles(files []InputFile) int {
+ size := 0
+ for _, file := range files {
+ size += len(file.Buffer)
+ }
+ return size
+}
+
+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 resolvePathsAndDirectoryForInputFiles(items []string) (localPaths []string, localDirectory *string, e error) {
+ for _, item := range items {
+ abspath, err := filepath.Abs(item)
+ if err != nil {
+ e = err
+ return
+ }
+ // if the path is a directory
+ if info, err := os.Stat(abspath); err == nil {
+ if info.IsDir() {
+ if localDirectory != nil {
+ e = errors.New("Multiple directories are not supported")
+ return
+ }
+ localDirectory = &abspath
+ } else {
+ if localPaths == nil {
+ localPaths = []string{abspath}
+ } else {
+ localPaths = append(localPaths, abspath)
+ }
+ }
+ } else {
+ e = err
+ return
+ }
+ }
+ if localPaths != nil && localDirectory != nil {
+ e = errors.New("File paths must be all files or a single directory")
+ }
+ return
+}
+
+func listFiles(dir string) ([]string, error) {
+ var files []string
+ err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ if !info.IsDir() {
+ files = append(files, path)
+ }
+ return nil
+ })
+ return files, err
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/internal/safe/map.go b/vendor/github.com/playwright-community/playwright-go/internal/safe/map.go
new file mode 100644
index 0000000..93a8800
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/internal/safe/map.go
@@ -0,0 +1,90 @@
+package safe
+
+import (
+ "maps"
+ "sync"
+)
+
+// SyncMap is a thread-safe map
+type SyncMap[K comparable, V any] struct {
+ sync.RWMutex
+ m map[K]V
+}
+
+// NewSyncMap creates a new thread-safe map
+func NewSyncMap[K comparable, V any]() *SyncMap[K, V] {
+ return &SyncMap[K, V]{
+ m: make(map[K]V),
+ }
+}
+
+func (m *SyncMap[K, V]) Store(k K, v V) {
+ m.Lock()
+ defer m.Unlock()
+ m.m[k] = v
+}
+
+func (m *SyncMap[K, V]) Load(k K) (v V, ok bool) {
+ m.RLock()
+ defer m.RUnlock()
+ v, ok = m.m[k]
+ return
+}
+
+// LoadOrStore returns the existing value for the key if present. Otherwise, it stores and returns the given value.
+func (m *SyncMap[K, V]) LoadOrStore(k K, v V) (actual V, loaded bool) {
+ m.Lock()
+ defer m.Unlock()
+ actual, loaded = m.m[k]
+ if loaded {
+ return
+ }
+ m.m[k] = v
+ return v, false
+}
+
+// LoadAndDelete deletes the value for a key, and returns the previous value if any.
+func (m *SyncMap[K, V]) LoadAndDelete(k K) (v V, loaded bool) {
+ m.Lock()
+ defer m.Unlock()
+ v, loaded = m.m[k]
+ if loaded {
+ delete(m.m, k)
+ }
+ return
+}
+
+func (m *SyncMap[K, V]) Delete(k K) {
+ m.Lock()
+ defer m.Unlock()
+ delete(m.m, k)
+}
+
+func (m *SyncMap[K, V]) Clear() {
+ m.Lock()
+ defer m.Unlock()
+ clear(m.m)
+}
+
+func (m *SyncMap[K, V]) Len() int {
+ m.RLock()
+ defer m.RUnlock()
+ return len(m.m)
+}
+
+func (m *SyncMap[K, V]) Clone() map[K]V {
+ m.RLock()
+ defer m.RUnlock()
+ return maps.Clone(m.m)
+}
+
+func (m *SyncMap[K, V]) Range(f func(k K, v V) bool) {
+ m.RLock()
+ defer m.RUnlock()
+
+ for k, v := range m.m {
+ if !f(k, v) {
+ break
+ }
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/js_handle.go b/vendor/github.com/playwright-community/playwright-go/js_handle.go
new file mode 100644
index 0000000..6aaa68d
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/js_handle.go
@@ -0,0 +1,421 @@
+package playwright
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "math"
+ "math/big"
+ "net/url"
+ "reflect"
+ "time"
+)
+
+type jsHandleImpl struct {
+ channelOwner
+ preview string
+}
+
+func (j *jsHandleImpl) Evaluate(expression string, options ...interface{}) (interface{}, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := j.channel.Send("evaluateExpression", map[string]interface{}{
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(result), nil
+}
+
+func (j *jsHandleImpl) EvaluateHandle(expression string, options ...interface{}) (JSHandle, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := j.channel.Send("evaluateExpressionHandle", map[string]interface{}{
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromChannel(result)
+ if channelOwner == nil {
+ return nil, nil
+ }
+ return channelOwner.(*jsHandleImpl), nil
+}
+
+func (j *jsHandleImpl) GetProperty(name string) (JSHandle, error) {
+ channel, err := j.channel.Send("getProperty", map[string]interface{}{
+ "name": name,
+ })
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(channel).(*jsHandleImpl), nil
+}
+
+func (j *jsHandleImpl) GetProperties() (map[string]JSHandle, error) {
+ properties, err := j.channel.Send("getPropertyList")
+ if err != nil {
+ return nil, err
+ }
+ propertiesMap := make(map[string]JSHandle)
+ for _, property := range properties.([]interface{}) {
+ item := property.(map[string]interface{})
+ propertiesMap[item["name"].(string)] = fromChannel(item["value"]).(*jsHandleImpl)
+ }
+ return propertiesMap, nil
+}
+
+func (j *jsHandleImpl) AsElement() ElementHandle {
+ return nil
+}
+
+func (j *jsHandleImpl) Dispose() error {
+ _, err := j.channel.Send("dispose")
+ if errors.Is(err, ErrTargetClosed) {
+ return nil
+ }
+ return err
+}
+
+func (j *jsHandleImpl) String() string {
+ return j.preview
+}
+
+func (j *jsHandleImpl) JSONValue() (interface{}, error) {
+ v, err := j.channel.Send("jsonValue")
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(v), nil
+}
+
+func parseValue(result interface{}, refs map[float64]interface{}) interface{} {
+ vMap, ok := result.(map[string]interface{})
+ if !ok {
+ return result
+ }
+ if v, ok := vMap["n"]; ok {
+ if math.Ceil(v.(float64))-v.(float64) == 0 {
+ return int(v.(float64))
+ }
+ return v.(float64)
+ }
+
+ if v, ok := vMap["u"]; ok {
+ u, _ := url.Parse(v.(string))
+ return u
+ }
+
+ if v, ok := vMap["bi"]; ok {
+ n := new(big.Int)
+ n.SetString(v.(string), 0)
+ return n
+ }
+
+ if v, ok := vMap["ref"]; ok {
+ if vV, ok := refs[v.(float64)]; ok {
+ return vV
+ }
+ return nil
+ }
+
+ if v, ok := vMap["s"]; ok {
+ return v.(string)
+ }
+ if v, ok := vMap["b"]; ok {
+ return v.(bool)
+ }
+ if v, ok := vMap["v"]; ok {
+ if v == "undefined" || v == "null" {
+ return nil
+ }
+ if v == "NaN" {
+ return math.NaN()
+ }
+ if v == "Infinity" {
+ return math.Inf(1)
+ }
+ if v == "-Infinity" {
+ return math.Inf(-1)
+ }
+ if v == "-0" {
+ return math.Copysign(0, -1)
+ }
+ return v
+ }
+ if v, ok := vMap["d"]; ok {
+ t, _ := time.Parse(time.RFC3339Nano, v.(string))
+ return t
+ }
+ if v, ok := vMap["a"]; ok {
+ aV := v.([]interface{})
+ refs[vMap["id"].(float64)] = aV
+ for i := range aV {
+ aV[i] = parseValue(aV[i], refs)
+ }
+ return aV
+ }
+ if v, ok := vMap["o"]; ok {
+ aV := v.([]interface{})
+ out := map[string]interface{}{}
+ refs[vMap["id"].(float64)] = out
+ for key := range aV {
+ entry := aV[key].(map[string]interface{})
+ out[entry["k"].(string)] = parseValue(entry["v"], refs)
+ }
+ return out
+ }
+
+ if v, ok := vMap["e"]; ok {
+ return parseError(Error{
+ Name: v.(map[string]interface{})["n"].(string),
+ Message: v.(map[string]interface{})["m"].(string),
+ Stack: v.(map[string]interface{})["s"].(string),
+ })
+ }
+ if v, ok := vMap["ta"]; ok {
+ b, b_ok := v.(map[string]interface{})["b"].(string)
+ k, k_ok := v.(map[string]interface{})["k"].(string)
+ if b_ok && k_ok {
+ decoded, err := base64.StdEncoding.DecodeString(b)
+ if err != nil {
+ panic(fmt.Errorf("Unexpected value: %v", vMap))
+ }
+ r := bytes.NewReader(decoded)
+ switch k {
+ case "i8":
+ result := make([]int8, len(decoded))
+ return mustReadArray(r, &result)
+ case "ui8", "ui8c":
+ result := make([]uint8, len(decoded))
+ return mustReadArray(r, &result)
+ case "i16":
+ size := mustBeDivisible(len(decoded), 2)
+ result := make([]int16, size)
+ return mustReadArray(r, &result)
+ case "ui16":
+ size := mustBeDivisible(len(decoded), 2)
+ result := make([]uint16, size)
+ return mustReadArray(r, &result)
+ case "i32":
+ size := mustBeDivisible(len(decoded), 4)
+ result := make([]int32, size)
+ return mustReadArray(r, &result)
+ case "ui32":
+ size := mustBeDivisible(len(decoded), 4)
+ result := make([]uint32, size)
+ return mustReadArray(r, &result)
+ case "f32":
+ size := mustBeDivisible(len(decoded), 4)
+ result := make([]float32, size)
+ return mustReadArray(r, &result)
+ case "f64":
+ size := mustBeDivisible(len(decoded), 8)
+ result := make([]float64, size)
+ return mustReadArray(r, &result)
+ case "bi64":
+ size := mustBeDivisible(len(decoded), 8)
+ result := make([]int64, size)
+ return mustReadArray(r, &result)
+ case "bui64":
+ size := mustBeDivisible(len(decoded), 8)
+ result := make([]uint64, size)
+ return mustReadArray(r, &result)
+ default:
+ panic(fmt.Errorf("Unsupported array type: %s", k))
+ }
+ }
+ }
+ panic(fmt.Errorf("Unexpected value: %v", vMap))
+}
+
+func serializeValue(value interface{}, handles *[]*channel, depth int) interface{} {
+ if handle, ok := value.(*elementHandleImpl); ok {
+ h := len(*handles)
+ *handles = append(*handles, handle.channel)
+ return map[string]interface{}{
+ "h": h,
+ }
+ }
+ if handle, ok := value.(*jsHandleImpl); ok {
+ h := len(*handles)
+ *handles = append(*handles, handle.channel)
+ return map[string]interface{}{
+ "h": h,
+ }
+ }
+ if u, ok := value.(*url.URL); ok {
+ return map[string]interface{}{
+ "u": u.String(),
+ }
+ }
+
+ if err, ok := value.(error); ok {
+ var e *Error
+ if errors.As(err, &e) {
+ return map[string]interface{}{
+ "e": map[string]interface{}{
+ "n": e.Name,
+ "m": e.Message,
+ "s": e.Stack,
+ },
+ }
+ }
+ return map[string]interface{}{
+ "e": map[string]interface{}{
+ "n": "",
+ "m": err.Error(),
+ "s": "",
+ },
+ }
+ }
+
+ if depth > 100 {
+ panic(errors.New("Maximum argument depth exceeded"))
+ }
+ if value == nil {
+ return map[string]interface{}{
+ "v": "undefined",
+ }
+ }
+ if n, ok := value.(*big.Int); ok {
+ return map[string]interface{}{
+ "bi": n.String(),
+ }
+ }
+
+ switch v := value.(type) {
+ case time.Time:
+ return map[string]interface{}{
+ "d": v.Format(time.RFC3339Nano),
+ }
+ case int:
+ return map[string]interface{}{
+ "n": v,
+ }
+ case string:
+ return map[string]interface{}{
+ "s": v,
+ }
+ case bool:
+ return map[string]interface{}{
+ "b": v,
+ }
+ }
+
+ refV := reflect.ValueOf(value)
+
+ switch refV.Kind() {
+ case reflect.Float32, reflect.Float64:
+ floatV := refV.Float()
+ if math.IsInf(floatV, 1) {
+ return map[string]interface{}{
+ "v": "Infinity",
+ }
+ }
+ if math.IsInf(floatV, -1) {
+ return map[string]interface{}{
+ "v": "-Infinity",
+ }
+ }
+ // https://github.com/golang/go/issues/2196
+ if floatV == math.Copysign(0, -1) {
+ return map[string]interface{}{
+ "v": "-0",
+ }
+ }
+ if math.IsNaN(floatV) {
+ return map[string]interface{}{
+ "v": "NaN",
+ }
+ }
+ return map[string]interface{}{
+ "n": floatV,
+ }
+ case reflect.Slice:
+ aV := make([]interface{}, refV.Len())
+ for i := 0; i < refV.Len(); i++ {
+ aV[i] = serializeValue(refV.Index(i).Interface(), handles, depth+1)
+ }
+ return map[string]interface{}{
+ "a": aV,
+ }
+ case reflect.Map:
+ out := []interface{}{}
+ vM := value.(map[string]interface{})
+ for key := range vM {
+ v := serializeValue(vM[key], handles, depth+1)
+ // had key, so convert "undefined" to "null"
+ if reflect.DeepEqual(v, map[string]interface{}{
+ "v": "undefined",
+ }) {
+ v = map[string]interface{}{
+ "v": "null",
+ }
+ }
+ out = append(out, map[string]interface{}{
+ "k": key,
+ "v": v,
+ })
+ }
+ return map[string]interface{}{
+ "o": out,
+ }
+ }
+ return map[string]interface{}{
+ "v": "undefined",
+ }
+}
+
+func parseResult(result interface{}) interface{} {
+ return parseValue(result, map[float64]interface{}{})
+}
+
+func serializeArgument(arg interface{}) interface{} {
+ handles := []*channel{}
+ value := serializeValue(arg, &handles, 0)
+ return map[string]interface{}{
+ "value": value,
+ "handles": handles,
+ }
+}
+
+func newJSHandle(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *jsHandleImpl {
+ bt := &jsHandleImpl{
+ preview: initializer["preview"].(string),
+ }
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ bt.channel.On("previewUpdated", func(ev map[string]interface{}) {
+ bt.preview = ev["preview"].(string)
+ })
+ return bt
+}
+
+func mustBeDivisible(length int, wordSize int) int {
+ if length%wordSize != 0 {
+ panic(fmt.Errorf(`Decoded bytes length %d is not a multiple of word size %d`, length, wordSize))
+ }
+ return length / wordSize
+}
+
+func mustReadArray[T int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | float32 | float64](r *bytes.Reader, v *[]T) []float64 {
+ err := binary.Read(r, binary.LittleEndian, v)
+ if err != nil {
+ panic(err)
+ }
+ data := make([]float64, len(*v))
+ for i, v := range *v {
+ data[i] = float64(v)
+ }
+ return data
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/jsonPipe.go b/vendor/github.com/playwright-community/playwright-go/jsonPipe.go
new file mode 100644
index 0000000..e6c0e79
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/jsonPipe.go
@@ -0,0 +1,64 @@
+package playwright
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+)
+
+type jsonPipe struct {
+ channelOwner
+ msgChan chan *message
+}
+
+func (j *jsonPipe) Send(message map[string]interface{}) error {
+ _, err := j.channel.Send("send", map[string]interface{}{
+ "message": message,
+ })
+ return err
+}
+
+func (j *jsonPipe) Close() error {
+ _, err := j.channel.Send("close")
+ return err
+}
+
+func (j *jsonPipe) Poll() (*message, error) {
+ msg := <-j.msgChan
+ if msg == nil {
+ return nil, errors.New("jsonPipe closed")
+ }
+ return msg, nil
+}
+
+func newJsonPipe(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *jsonPipe {
+ j := &jsonPipe{
+ msgChan: make(chan *message, 2),
+ }
+ j.createChannelOwner(j, parent, objectType, guid, initializer)
+ j.channel.On("message", func(ev map[string]interface{}) {
+ var msg message
+ m, err := json.Marshal(ev["message"])
+ if err == nil {
+ err = json.Unmarshal(m, &msg)
+ }
+ if err != nil {
+ msg = message{
+ Error: &struct {
+ Error Error "json:\"error\""
+ }{
+ Error: Error{
+ Name: "Error",
+ Message: fmt.Sprintf("jsonPipe: could not decode message: %s", err.Error()),
+ },
+ },
+ }
+ }
+ j.msgChan <- &msg
+ })
+ j.channel.Once("closed", func() {
+ j.Emit("closed")
+ close(j.msgChan)
+ })
+ return j
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/local_utils.go b/vendor/github.com/playwright-community/playwright-go/local_utils.go
new file mode 100644
index 0000000..395c09a
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/local_utils.go
@@ -0,0 +1,165 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+)
+
+type localUtilsImpl struct {
+ channelOwner
+ Devices map[string]*DeviceDescriptor
+}
+
+type (
+ localUtilsZipOptions struct {
+ ZipFile string `json:"zipFile"`
+ Entries []interface{} `json:"entries"`
+ StacksId string `json:"stacksId"`
+ Mode string `json:"mode"`
+ IncludeSources bool `json:"includeSources"`
+ }
+
+ harLookupOptions struct {
+ HarId string `json:"harId"`
+ URL string `json:"url"`
+ Method string `json:"method"`
+ Headers map[string]string `json:"headers"`
+ IsNavigationRequest bool `json:"isNavigationRequest"`
+ PostData interface{} `json:"postData,omitempty"`
+ }
+
+ harLookupResult struct {
+ Action string `json:"action"`
+ Message *string `json:"message,omitempty"`
+ RedirectURL *string `json:"redirectUrl,omitempty"`
+ Status *int `json:"status,omitempty"`
+ Headers []map[string]string `json:"headers,omitempty"`
+ Body *string `json:"body,omitempty"`
+ }
+)
+
+func (l *localUtilsImpl) Zip(options localUtilsZipOptions) (interface{}, error) {
+ return l.channel.Send("zip", options)
+}
+
+func (l *localUtilsImpl) HarOpen(file string) (string, error) {
+ result, err := l.channel.SendReturnAsDict("harOpen", []map[string]interface{}{
+ {
+ "file": file,
+ },
+ })
+ if err == nil {
+ if harId, ok := result["harId"]; ok {
+ return harId.(string), nil
+ }
+ if err, ok := result["error"]; ok {
+ return "", fmt.Errorf("%w:%v", ErrPlaywright, err)
+ }
+ }
+ return "", err
+}
+
+func (l *localUtilsImpl) HarLookup(option harLookupOptions) (*harLookupResult, error) {
+ overrides := make(map[string]interface{})
+ overrides["harId"] = option.HarId
+ overrides["url"] = option.URL
+ overrides["method"] = option.Method
+ if option.Headers != nil {
+ overrides["headers"] = serializeMapToNameAndValue(option.Headers)
+ }
+ overrides["isNavigationRequest"] = option.IsNavigationRequest
+ if option.PostData != nil {
+ switch v := option.PostData.(type) {
+ case string:
+ overrides["postData"] = base64.StdEncoding.EncodeToString([]byte(v))
+ case []byte:
+ overrides["postData"] = base64.StdEncoding.EncodeToString(v)
+ }
+ }
+ ret, err := l.channel.SendReturnAsDict("harLookup", overrides)
+ if ret == nil {
+ return nil, err
+ }
+ var result harLookupResult
+ mJson, err := json.Marshal(ret)
+ if err != nil {
+ return nil, err
+ }
+ err = json.Unmarshal(mJson, &result)
+ if err != nil {
+ return nil, err
+ }
+ if result.Body != nil {
+ body, err := base64.StdEncoding.DecodeString(*result.Body)
+ if err != nil {
+ return nil, err
+ }
+ result.Body = String(string(body))
+ }
+ return &result, err
+}
+
+func (l *localUtilsImpl) HarClose(harId string) error {
+ _, err := l.channel.Send("harClose", []map[string]interface{}{
+ {
+ "harId": harId,
+ },
+ })
+ return err
+}
+
+func (l *localUtilsImpl) HarUnzip(zipFile, harFile string) error {
+ _, err := l.channel.Send("harUnzip", []map[string]interface{}{
+ {
+ "zipFile": zipFile,
+ "harFile": harFile,
+ },
+ })
+ return err
+}
+
+func (l *localUtilsImpl) TracingStarted(traceName string, tracesDir ...string) (string, error) {
+ overrides := make(map[string]interface{})
+ overrides["traceName"] = traceName
+ if len(tracesDir) > 0 {
+ overrides["tracesDir"] = tracesDir[0]
+ }
+ stacksId, err := l.channel.Send("tracingStarted", overrides)
+ if stacksId == nil {
+ return "", err
+ }
+ return stacksId.(string), err
+}
+
+func (l *localUtilsImpl) TraceDiscarded(stacksId string) error {
+ _, err := l.channel.Send("traceDiscarded", map[string]interface{}{
+ "stacksId": stacksId,
+ })
+ return err
+}
+
+func (l *localUtilsImpl) AddStackToTracingNoReply(id uint32, stack []map[string]interface{}) {
+ l.channel.SendNoReply("addStackToTracingNoReply", map[string]interface{}{
+ "callData": map[string]interface{}{
+ "id": id,
+ "stack": stack,
+ },
+ })
+}
+
+func newLocalUtils(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *localUtilsImpl {
+ l := &localUtilsImpl{
+ Devices: make(map[string]*DeviceDescriptor),
+ }
+ l.createChannelOwner(l, parent, objectType, guid, initializer)
+ for _, dd := range initializer["deviceDescriptors"].([]interface{}) {
+ entry := dd.(map[string]interface{})
+ l.Devices[entry["name"].(string)] = &DeviceDescriptor{
+ Viewport: &Size{},
+ }
+ remapMapToStruct(entry["descriptor"], l.Devices[entry["name"].(string)])
+ }
+ l.markAsInternalType()
+ return l
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/locator.go b/vendor/github.com/playwright-community/playwright-go/locator.go
new file mode 100644
index 0000000..e6a49b7
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/locator.go
@@ -0,0 +1,914 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+)
+
+var (
+ testIdAttributeName = "data-testid"
+ ErrLocatorNotSameFrame = errors.New("inner 'has' or 'hasNot' locator must belong to the same frame")
+)
+
+type locatorImpl struct {
+ frame *frameImpl
+ selector string
+ options *LocatorOptions
+ err error
+}
+
+type LocatorOptions LocatorFilterOptions
+
+func newLocator(frame *frameImpl, selector string, options ...LocatorOptions) *locatorImpl {
+ option := &LocatorOptions{}
+ if len(options) == 1 {
+ option = &options[0]
+ }
+ locator := &locatorImpl{frame: frame, selector: selector, options: option, err: nil}
+ if option.HasText != nil {
+ selector += fmt.Sprintf(` >> internal:has-text=%s`, escapeForTextSelector(option.HasText, false))
+ }
+ if option.HasNotText != nil {
+ selector += fmt.Sprintf(` >> internal:has-not-text=%s`, escapeForTextSelector(option.HasNotText, false))
+ }
+ if option.Has != nil {
+ has := option.Has.(*locatorImpl)
+ if frame != has.frame {
+ locator.err = errors.Join(locator.err, ErrLocatorNotSameFrame)
+ } else {
+ selector += fmt.Sprintf(` >> internal:has=%s`, escapeText(has.selector))
+ }
+ }
+ if option.HasNot != nil {
+ hasNot := option.HasNot.(*locatorImpl)
+ if frame != hasNot.frame {
+ locator.err = errors.Join(locator.err, ErrLocatorNotSameFrame)
+ } else {
+ selector += fmt.Sprintf(` >> internal:has-not=%s`, escapeText(hasNot.selector))
+ }
+ }
+ if option.Visible != nil {
+ selector += fmt.Sprintf(` >> visible=%s`, strconv.FormatBool(*option.Visible))
+ }
+
+ locator.selector = selector
+
+ return locator
+}
+
+func (l *locatorImpl) equals(locator Locator) bool {
+ return l.frame == locator.(*locatorImpl).frame && l.err == locator.(*locatorImpl).err && l.selector == locator.(*locatorImpl).selector
+}
+
+func (l *locatorImpl) Err() error {
+ return l.err
+}
+
+func (l *locatorImpl) All() ([]Locator, error) {
+ result := make([]Locator, 0)
+ count, err := l.Count()
+ if err != nil {
+ return nil, err
+ }
+ for i := 0; i < count; i++ {
+ result = append(result, l.Nth(i))
+ }
+ return result, nil
+}
+
+func (l *locatorImpl) AllInnerTexts() ([]string, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ innerTexts, err := l.frame.EvalOnSelectorAll(l.selector, "ee => ee.map(e => e.innerText)")
+ if err != nil {
+ return nil, err
+ }
+ texts := innerTexts.([]interface{})
+ result := make([]string, len(texts))
+ for i := range texts {
+ result[i] = texts[i].(string)
+ }
+ return result, nil
+}
+
+func (l *locatorImpl) AllTextContents() ([]string, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ textContents, err := l.frame.EvalOnSelectorAll(l.selector, "ee => ee.map(e => e.textContent || '')")
+ if err != nil {
+ return nil, err
+ }
+ texts := textContents.([]interface{})
+ result := make([]string, len(texts))
+ for i := range texts {
+ result[i] = texts[i].(string)
+ }
+ return result, nil
+}
+
+func (l *locatorImpl) And(locator Locator) Locator {
+ return newLocator(l.frame, l.selector+` >> internal:and=`+escapeText(locator.(*locatorImpl).selector))
+}
+
+func (l *locatorImpl) Or(locator Locator) Locator {
+ return newLocator(l.frame, l.selector+` >> internal:or=`+escapeText(locator.(*locatorImpl).selector))
+}
+
+func (l *locatorImpl) Blur(options ...LocatorBlurOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ params := map[string]interface{}{
+ "selector": l.selector,
+ "strict": true,
+ }
+ if len(options) == 1 {
+ if options[0].Timeout != nil {
+ params["timeout"] = options[0].Timeout
+ }
+ }
+ _, err := l.frame.channel.Send("blur", params)
+ return err
+}
+
+func (l *locatorImpl) AriaSnapshot(options ...LocatorAriaSnapshotOptions) (string, error) {
+ var option LocatorAriaSnapshotOptions
+ if len(options) == 1 {
+ option = options[0]
+ }
+ ret, err := l.frame.channel.Send("ariaSnapshot", option,
+ map[string]interface{}{"selector": l.selector})
+ if err != nil {
+ return "", err
+ }
+ return ret.(string), nil
+}
+
+func (l *locatorImpl) BoundingBox(options ...LocatorBoundingBoxOptions) (*Rect, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ var option FrameWaitForSelectorOptions
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ }
+
+ result, err := l.withElement(func(handle ElementHandle) (interface{}, error) {
+ return handle.BoundingBox()
+ }, option)
+ if err != nil {
+ return nil, err
+ }
+
+ return result.(*Rect), nil
+}
+
+func (l *locatorImpl) Check(options ...LocatorCheckOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameCheckOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Check(l.selector, opt)
+}
+
+func (l *locatorImpl) Clear(options ...LocatorClearOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ if len(options) == 1 {
+ return l.Fill("", LocatorFillOptions{
+ Force: options[0].Force,
+ Timeout: options[0].Timeout,
+ })
+ } else {
+ return l.Fill("")
+ }
+}
+
+func (l *locatorImpl) Click(options ...LocatorClickOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameClickOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Click(l.selector, opt)
+}
+
+func (l *locatorImpl) ContentFrame() FrameLocator {
+ return newFrameLocator(l.frame, l.selector)
+}
+
+func (l *locatorImpl) Count() (int, error) {
+ if l.err != nil {
+ return 0, l.err
+ }
+ return l.frame.queryCount(l.selector)
+}
+
+func (l *locatorImpl) Dblclick(options ...LocatorDblclickOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameDblclickOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Dblclick(l.selector, opt)
+}
+
+func (l *locatorImpl) DispatchEvent(typ string, eventInit interface{}, options ...LocatorDispatchEventOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameDispatchEventOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.DispatchEvent(l.selector, typ, eventInit, opt)
+}
+
+func (l *locatorImpl) DragTo(target Locator, options ...LocatorDragToOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameDragAndDropOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.DragAndDrop(l.selector, target.(*locatorImpl).selector, opt)
+}
+
+func (l *locatorImpl) ElementHandle(options ...LocatorElementHandleOptions) (ElementHandle, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ option := FrameWaitForSelectorOptions{
+ State: WaitForSelectorStateAttached,
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&option, options[0], false); err != nil {
+ return nil, err
+ }
+ }
+ return l.frame.WaitForSelector(l.selector, option)
+}
+
+func (l *locatorImpl) ElementHandles() ([]ElementHandle, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ return l.frame.QuerySelectorAll(l.selector)
+}
+
+func (l *locatorImpl) Evaluate(expression string, arg interface{}, options ...LocatorEvaluateOptions) (interface{}, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ var option FrameWaitForSelectorOptions
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ }
+
+ return l.withElement(func(handle ElementHandle) (interface{}, error) {
+ return handle.Evaluate(expression, arg)
+ }, option)
+}
+
+func (l *locatorImpl) EvaluateAll(expression string, options ...interface{}) (interface{}, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ return l.frame.EvalOnSelectorAll(l.selector, expression, options...)
+}
+
+func (l *locatorImpl) EvaluateHandle(expression string, arg interface{}, options ...LocatorEvaluateHandleOptions) (JSHandle, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ var option FrameWaitForSelectorOptions
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ }
+
+ h, err := l.withElement(func(handle ElementHandle) (interface{}, error) {
+ return handle.EvaluateHandle(expression, arg)
+ }, option)
+ if err != nil {
+ return nil, err
+ }
+ return h.(JSHandle), nil
+}
+
+func (l *locatorImpl) Fill(value string, options ...LocatorFillOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameFillOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Fill(l.selector, value, opt)
+}
+
+func (l *locatorImpl) Filter(options ...LocatorFilterOptions) Locator {
+ if len(options) == 1 {
+ return newLocator(l.frame, l.selector, LocatorOptions(options[0]))
+ }
+ return newLocator(l.frame, l.selector)
+}
+
+func (l *locatorImpl) First() Locator {
+ return newLocator(l.frame, l.selector+" >> nth=0")
+}
+
+func (l *locatorImpl) Focus(options ...LocatorFocusOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameFocusOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Focus(l.selector, opt)
+}
+
+func (l *locatorImpl) FrameLocator(selector string) FrameLocator {
+ return newFrameLocator(l.frame, l.selector+" >> "+selector)
+}
+
+func (l *locatorImpl) GetAttribute(name string, options ...LocatorGetAttributeOptions) (string, error) {
+ if l.err != nil {
+ return "", l.err
+ }
+ opt := FrameGetAttributeOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return "", err
+ }
+ }
+ return l.frame.GetAttribute(l.selector, name, opt)
+}
+
+func (l *locatorImpl) GetByAltText(text interface{}, options ...LocatorGetByAltTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return l.Locator(getByAltTextSelector(text, exact))
+}
+
+func (l *locatorImpl) GetByLabel(text interface{}, options ...LocatorGetByLabelOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return l.Locator(getByLabelSelector(text, exact))
+}
+
+func (l *locatorImpl) GetByPlaceholder(text interface{}, options ...LocatorGetByPlaceholderOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return l.Locator(getByPlaceholderSelector(text, exact))
+}
+
+func (l *locatorImpl) GetByRole(role AriaRole, options ...LocatorGetByRoleOptions) Locator {
+ return l.Locator(getByRoleSelector(role, options...))
+}
+
+func (l *locatorImpl) GetByTestId(testId interface{}) Locator {
+ return l.Locator(getByTestIdSelector(getTestIdAttributeName(), testId))
+}
+
+func (l *locatorImpl) GetByText(text interface{}, options ...LocatorGetByTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return l.Locator(getByTextSelector(text, exact))
+}
+
+func (l *locatorImpl) GetByTitle(text interface{}, options ...LocatorGetByTitleOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return l.Locator(getByTitleSelector(text, exact))
+}
+
+func (l *locatorImpl) Highlight() error {
+ if l.err != nil {
+ return l.err
+ }
+ return l.frame.highlight(l.selector)
+}
+
+func (l *locatorImpl) Hover(options ...LocatorHoverOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameHoverOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Hover(l.selector, opt)
+}
+
+func (l *locatorImpl) InnerHTML(options ...LocatorInnerHTMLOptions) (string, error) {
+ if l.err != nil {
+ return "", l.err
+ }
+ opt := FrameInnerHTMLOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return "", err
+ }
+ }
+ return l.frame.InnerHTML(l.selector, opt)
+}
+
+func (l *locatorImpl) InnerText(options ...LocatorInnerTextOptions) (string, error) {
+ if l.err != nil {
+ return "", l.err
+ }
+ opt := FrameInnerTextOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return "", err
+ }
+ }
+ return l.frame.InnerText(l.selector, opt)
+}
+
+func (l *locatorImpl) InputValue(options ...LocatorInputValueOptions) (string, error) {
+ if l.err != nil {
+ return "", l.err
+ }
+ opt := FrameInputValueOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return "", err
+ }
+ }
+ return l.frame.InputValue(l.selector, opt)
+}
+
+func (l *locatorImpl) IsChecked(options ...LocatorIsCheckedOptions) (bool, error) {
+ if l.err != nil {
+ return false, l.err
+ }
+ opt := FrameIsCheckedOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return false, err
+ }
+ }
+ return l.frame.IsChecked(l.selector, opt)
+}
+
+func (l *locatorImpl) IsDisabled(options ...LocatorIsDisabledOptions) (bool, error) {
+ if l.err != nil {
+ return false, l.err
+ }
+ opt := FrameIsDisabledOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return false, err
+ }
+ }
+ return l.frame.IsDisabled(l.selector, opt)
+}
+
+func (l *locatorImpl) IsEditable(options ...LocatorIsEditableOptions) (bool, error) {
+ if l.err != nil {
+ return false, l.err
+ }
+ opt := FrameIsEditableOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return false, err
+ }
+ }
+ return l.frame.IsEditable(l.selector, opt)
+}
+
+func (l *locatorImpl) IsEnabled(options ...LocatorIsEnabledOptions) (bool, error) {
+ if l.err != nil {
+ return false, l.err
+ }
+ opt := FrameIsEnabledOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return false, err
+ }
+ }
+ return l.frame.IsEnabled(l.selector, opt)
+}
+
+func (l *locatorImpl) IsHidden(options ...LocatorIsHiddenOptions) (bool, error) {
+ if l.err != nil {
+ return false, l.err
+ }
+ opt := FrameIsHiddenOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return false, err
+ }
+ }
+ return l.frame.IsHidden(l.selector, opt)
+}
+
+func (l *locatorImpl) IsVisible(options ...LocatorIsVisibleOptions) (bool, error) {
+ if l.err != nil {
+ return false, l.err
+ }
+ opt := FrameIsVisibleOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return false, err
+ }
+ }
+ return l.frame.IsVisible(l.selector, opt)
+}
+
+func (l *locatorImpl) Last() Locator {
+ return newLocator(l.frame, l.selector+" >> nth=-1")
+}
+
+func (l *locatorImpl) Locator(selectorOrLocator interface{}, options ...LocatorLocatorOptions) Locator {
+ var option LocatorOptions
+ if len(options) == 1 {
+ option = LocatorOptions{
+ Has: options[0].Has,
+ HasNot: options[0].HasNot,
+ HasText: options[0].HasText,
+ HasNotText: options[0].HasNotText,
+ }
+ }
+
+ selector, ok := selectorOrLocator.(string)
+ if ok {
+ return newLocator(l.frame, l.selector+" >> "+selector, option)
+ }
+ locator, ok := selectorOrLocator.(*locatorImpl)
+ if ok {
+ if l.frame != locator.frame {
+ l.err = errors.Join(l.err, ErrLocatorNotSameFrame)
+ return l
+ }
+ return newLocator(l.frame,
+ l.selector+" >> internal:chain="+escapeText(locator.selector),
+ option,
+ )
+ }
+ l.err = errors.Join(l.err, fmt.Errorf("invalid locator parameter: %v", selectorOrLocator))
+ return l
+}
+
+func (l *locatorImpl) Nth(index int) Locator {
+ return newLocator(l.frame, l.selector+" >> nth="+strconv.Itoa(index))
+}
+
+func (l *locatorImpl) Page() (Page, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ return l.frame.Page(), nil
+}
+
+func (l *locatorImpl) Press(key string, options ...LocatorPressOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FramePressOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Press(l.selector, key, opt)
+}
+
+func (l *locatorImpl) PressSequentially(text string, options ...LocatorPressSequentiallyOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ var option LocatorTypeOptions
+ if len(options) == 1 {
+ option = LocatorTypeOptions(options[0])
+ }
+ return l.Type(text, option)
+}
+
+func (l *locatorImpl) Screenshot(options ...LocatorScreenshotOptions) ([]byte, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ var option FrameWaitForSelectorOptions
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ }
+
+ result, err := l.withElement(func(handle ElementHandle) (interface{}, error) {
+ var screenshotOption ElementHandleScreenshotOptions
+ if len(options) == 1 {
+ screenshotOption = ElementHandleScreenshotOptions(options[0])
+ }
+ return handle.Screenshot(screenshotOption)
+ }, option)
+ if err != nil {
+ return nil, err
+ }
+
+ return result.([]byte), nil
+}
+
+func (l *locatorImpl) ScrollIntoViewIfNeeded(options ...LocatorScrollIntoViewIfNeededOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ var option FrameWaitForSelectorOptions
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ }
+
+ _, err := l.withElement(func(handle ElementHandle) (interface{}, error) {
+ var opt ElementHandleScrollIntoViewIfNeededOptions
+ if len(options) == 1 {
+ opt.Timeout = options[0].Timeout
+ }
+ return nil, handle.ScrollIntoViewIfNeeded(opt)
+ }, option)
+
+ return err
+}
+
+func (l *locatorImpl) SelectOption(values SelectOptionValues, options ...LocatorSelectOptionOptions) ([]string, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ opt := FrameSelectOptionOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return nil, err
+ }
+ }
+ return l.frame.SelectOption(l.selector, values, opt)
+}
+
+func (l *locatorImpl) SelectText(options ...LocatorSelectTextOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ var option FrameWaitForSelectorOptions
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ }
+
+ _, err := l.withElement(func(handle ElementHandle) (interface{}, error) {
+ var opt ElementHandleSelectTextOptions
+ if len(options) == 1 {
+ opt = ElementHandleSelectTextOptions(options[0])
+ }
+ return nil, handle.SelectText(opt)
+ }, option)
+
+ return err
+}
+
+func (l *locatorImpl) SetChecked(checked bool, options ...LocatorSetCheckedOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameSetCheckedOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.SetChecked(l.selector, checked, opt)
+}
+
+func (l *locatorImpl) SetInputFiles(files interface{}, options ...LocatorSetInputFilesOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameSetInputFilesOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.SetInputFiles(l.selector, files, opt)
+}
+
+func (l *locatorImpl) Tap(options ...LocatorTapOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameTapOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Tap(l.selector, opt)
+}
+
+func (l *locatorImpl) TextContent(options ...LocatorTextContentOptions) (string, error) {
+ if l.err != nil {
+ return "", l.err
+ }
+ opt := FrameTextContentOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return "", err
+ }
+ }
+ return l.frame.TextContent(l.selector, opt)
+}
+
+func (l *locatorImpl) Type(text string, options ...LocatorTypeOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameTypeOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Type(l.selector, text, opt)
+}
+
+func (l *locatorImpl) Uncheck(options ...LocatorUncheckOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameUncheckOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Uncheck(l.selector, opt)
+}
+
+func (l *locatorImpl) WaitFor(options ...LocatorWaitForOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameWaitForSelectorOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ _, err := l.frame.WaitForSelector(l.selector, opt)
+ return err
+}
+
+func (l *locatorImpl) withElement(
+ callback func(handle ElementHandle) (interface{}, error),
+ options ...FrameWaitForSelectorOptions,
+) (interface{}, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ handle, err := l.frame.WaitForSelector(l.selector, options...)
+ if err != nil {
+ return nil, err
+ }
+
+ result, err := callback(handle)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+func (l *locatorImpl) expect(expression string, options frameExpectOptions) (*frameExpectResult, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ overrides := map[string]interface{}{
+ "selector": l.selector,
+ "expression": expression,
+ }
+ if options.ExpectedValue != nil {
+ overrides["expectedValue"] = serializeArgument(options.ExpectedValue)
+ options.ExpectedValue = nil
+ }
+ result, err := l.frame.channel.SendReturnAsDict("expect", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ var (
+ received interface{}
+ matches bool
+ log []string
+ )
+
+ if v, ok := result["received"]; ok {
+ received = parseResult(v)
+ }
+ if v, ok := result["matches"]; ok {
+ matches = v.(bool)
+ }
+ if v, ok := result["log"]; ok {
+ for _, l := range v.([]interface{}) {
+ log = append(log, l.(string))
+ }
+ }
+ return &frameExpectResult{Received: received, Matches: matches, Log: log}, nil
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/locator_assertions.go b/vendor/github.com/playwright-community/playwright-go/locator_assertions.go
new file mode 100644
index 0000000..e2ea2bb
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/locator_assertions.go
@@ -0,0 +1,568 @@
+package playwright
+
+import (
+ "fmt"
+ "regexp"
+)
+
+type locatorAssertionsImpl struct {
+ assertionsBase
+}
+
+func newLocatorAssertions(locator Locator, isNot bool, defaultTimeout *float64) *locatorAssertionsImpl {
+ return &locatorAssertionsImpl{
+ assertionsBase: assertionsBase{
+ actualLocator: locator,
+ isNot: isNot,
+ defaultTimeout: defaultTimeout,
+ },
+ }
+}
+
+func (la *locatorAssertionsImpl) ToBeAttached(options ...LocatorAssertionsToBeAttachedOptions) error {
+ expression := "to.be.attached"
+ var timeout *float64
+ if len(options) == 1 {
+ if options[0].Attached != nil && !*options[0].Attached {
+ expression = "to.be.detached"
+ }
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ expression,
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be attached",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeChecked(options ...LocatorAssertionsToBeCheckedOptions) error {
+ var timeout *float64
+
+ expectedValue := map[string]interface{}{}
+ expected := "checked"
+
+ if len(options) == 1 {
+ if options[0].Indeterminate != nil {
+ expectedValue["indeterminate"] = *options[0].Indeterminate
+ if *options[0].Indeterminate {
+ expected = "indeterminate"
+ }
+ } else {
+ if options[0].Checked != nil {
+ expectedValue["checked"] = *options[0].Checked
+ if !*options[0].Checked {
+ expected = "unchecked"
+ }
+ }
+ }
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.checked",
+ frameExpectOptions{
+ ExpectedValue: expectedValue,
+ Timeout: timeout,
+ },
+ nil,
+ fmt.Sprintf("Locator expected to be %s", expected),
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeDisabled(options ...LocatorAssertionsToBeDisabledOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.disabled",
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be disabled",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeEditable(options ...LocatorAssertionsToBeEditableOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.editable",
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be editable",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeEmpty(options ...LocatorAssertionsToBeEmptyOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.empty",
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be empty",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeEnabled(options ...LocatorAssertionsToBeEnabledOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.enabled",
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be enabled",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeFocused(options ...LocatorAssertionsToBeFocusedOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.focused",
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be focused",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeHidden(options ...LocatorAssertionsToBeHiddenOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.hidden",
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be hidden",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeInViewport(options ...LocatorAssertionsToBeInViewportOptions) error {
+ var (
+ ratio *float64
+ timeout *float64
+ )
+ if len(options) == 1 {
+ ratio = options[0].Ratio
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.in.viewport",
+ frameExpectOptions{
+ ExpectedNumber: ratio,
+ Timeout: timeout,
+ },
+ nil,
+ "Locator expected to be in viewport",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeVisible(options ...LocatorAssertionsToBeVisibleOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.visible",
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be visible",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToContainClass(expected interface{}, options ...LocatorAssertionsToContainClassOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ switch expected.(type) {
+ case []string:
+ expectedText, err := toExpectedTextValues(convertToInterfaceList(expected), false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.contain.class.array",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to contain class",
+ )
+ case string:
+ expectedText, err := toExpectedTextValues([]interface{}{expected}, false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.contain.class",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to contain class",
+ )
+ default:
+ return fmt.Errorf("expected should be string or []string, but got %T", expected)
+ }
+}
+
+func (la *locatorAssertionsImpl) ToContainText(expected interface{}, options ...LocatorAssertionsToContainTextOptions) error {
+ var (
+ timeout *float64
+ useInnerText *bool
+ ignoreCase *bool
+ )
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ useInnerText = options[0].UseInnerText
+ ignoreCase = options[0].IgnoreCase
+ }
+
+ switch expected.(type) {
+ case []string, []*regexp.Regexp:
+ expectedText, err := toExpectedTextValues(convertToInterfaceList(expected), true, true, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.contain.text.array",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ UseInnerText: useInnerText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to contain text",
+ )
+ default:
+ expectedText, err := toExpectedTextValues([]interface{}{expected}, true, true, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.text",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ UseInnerText: useInnerText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to contain text",
+ )
+ }
+}
+
+func (la *locatorAssertionsImpl) ToHaveAccessibleDescription(description interface{}, options ...LocatorAssertionsToHaveAccessibleDescriptionOptions) error {
+ var timeout *float64
+ var ignoreCase *bool
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ ignoreCase = options[0].IgnoreCase
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{description}, false, false, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.accessible.description",
+ frameExpectOptions{ExpectedText: expectedText, Timeout: timeout},
+ description,
+ "Locator expected to have AccessibleDescription",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveAccessibleErrorMessage(errorMessage interface{}, options ...LocatorAssertionsToHaveAccessibleErrorMessageOptions) error {
+ var timeout *float64
+ var ignoreCase *bool
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ ignoreCase = options[0].IgnoreCase
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{errorMessage}, false, false, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.accessible.error.message",
+ frameExpectOptions{ExpectedText: expectedText, Timeout: timeout},
+ errorMessage,
+ "Locator expected to have AccessibleErrorMessage",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveAccessibleName(name interface{}, options ...LocatorAssertionsToHaveAccessibleNameOptions) error {
+ var timeout *float64
+ var ignoreCase *bool
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ ignoreCase = options[0].IgnoreCase
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{name}, false, false, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.accessible.name",
+ frameExpectOptions{ExpectedText: expectedText, Timeout: timeout},
+ name,
+ "Locator expected to have AccessibleName",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveAttribute(name string, value interface{}, options ...LocatorAssertionsToHaveAttributeOptions) error {
+ var timeout *float64
+ var ignoreCase *bool
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ ignoreCase = options[0].IgnoreCase
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{value}, false, false, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.attribute.value",
+ frameExpectOptions{
+ ExpressionArg: name,
+ ExpectedText: expectedText,
+ Timeout: timeout,
+ },
+ value,
+ "Locator expected to have attribute",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveClass(expected interface{}, options ...LocatorAssertionsToHaveClassOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ switch expected.(type) {
+ case []string, []*regexp.Regexp:
+ expectedText, err := toExpectedTextValues(convertToInterfaceList(expected), false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.class.array",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to have class",
+ )
+ default:
+ expectedText, err := toExpectedTextValues([]interface{}{expected}, false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.class",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to have class",
+ )
+ }
+}
+
+func (la *locatorAssertionsImpl) ToHaveCount(count int, options ...LocatorAssertionsToHaveCountOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.have.count",
+ frameExpectOptions{ExpectedNumber: Float(float64(count)), Timeout: timeout},
+ count,
+ "Locator expected to have count",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveCSS(name string, value interface{}, options ...LocatorAssertionsToHaveCSSOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{value}, false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.css",
+ frameExpectOptions{
+ ExpressionArg: name,
+ ExpectedText: expectedText,
+ Timeout: timeout,
+ },
+ value,
+ "Locator expected to have CSS",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveId(id interface{}, options ...LocatorAssertionsToHaveIdOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{id}, false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.id",
+ frameExpectOptions{ExpectedText: expectedText, Timeout: timeout},
+ id,
+ "Locator expected to have ID",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveJSProperty(name string, value interface{}, options ...LocatorAssertionsToHaveJSPropertyOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.have.property",
+ frameExpectOptions{
+ ExpressionArg: name,
+ ExpectedValue: value,
+ Timeout: timeout,
+ },
+ value,
+ "Locator expected to have JS Property",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveRole(role AriaRole, options ...LocatorAssertionsToHaveRoleOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{string(role)}, false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.role",
+ frameExpectOptions{ExpectedText: expectedText, Timeout: timeout},
+ role,
+ "Locator expected to have Role",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveText(expected interface{}, options ...LocatorAssertionsToHaveTextOptions) error {
+ var (
+ timeout *float64
+ useInnerText *bool
+ ignoreCase *bool
+ )
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ useInnerText = options[0].UseInnerText
+ ignoreCase = options[0].IgnoreCase
+ }
+
+ switch expected.(type) {
+ case []string, []*regexp.Regexp:
+ expectedText, err := toExpectedTextValues(convertToInterfaceList(expected), false, true, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.text.array",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ UseInnerText: useInnerText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to have text",
+ )
+ default:
+ expectedText, err := toExpectedTextValues([]interface{}{expected}, false, true, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.text",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ UseInnerText: useInnerText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to have text",
+ )
+ }
+}
+
+func (la *locatorAssertionsImpl) ToHaveValue(value interface{}, options ...LocatorAssertionsToHaveValueOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{value}, false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.value",
+ frameExpectOptions{ExpectedText: expectedText, Timeout: timeout},
+ value,
+ "Locator expected to have Value",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveValues(values []interface{}, options ...LocatorAssertionsToHaveValuesOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ expectedText, err := toExpectedTextValues(values, false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.values",
+ frameExpectOptions{ExpectedText: expectedText, Timeout: timeout},
+ values,
+ "Locator expected to have Values",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToMatchAriaSnapshot(expected string, options ...LocatorAssertionsToMatchAriaSnapshotOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.match.aria",
+ frameExpectOptions{
+ ExpectedValue: expected,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to match Aria snapshot",
+ )
+}
+
+func (la *locatorAssertionsImpl) Not() LocatorAssertions {
+ return newLocatorAssertions(la.actualLocator, true, la.defaultTimeout)
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/locator_helpers.go b/vendor/github.com/playwright-community/playwright-go/locator_helpers.go
new file mode 100644
index 0000000..2836fca
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/locator_helpers.go
@@ -0,0 +1,133 @@
+package playwright
+
+import (
+ "encoding/json"
+ "fmt"
+ "regexp"
+ "strings"
+)
+
+func convertRegexp(reg *regexp.Regexp) (pattern, flags string) {
+ matches := regexp.MustCompile(`\(\?([imsU]+)\)(.+)`).FindStringSubmatch(reg.String())
+
+ if len(matches) == 3 {
+ pattern = matches[2]
+ flags = matches[1]
+ } else {
+ pattern = reg.String()
+ }
+ return
+}
+
+func escapeForAttributeSelector(text interface{}, exact bool) string {
+ switch text := text.(type) {
+ case *regexp.Regexp:
+ return escapeRegexForSelector(text)
+ default:
+ suffix := "i"
+ if exact {
+ suffix = "s"
+ }
+ return fmt.Sprintf(`"%s"%s`, strings.Replace(strings.Replace(text.(string), `\`, `\\`, -1), `"`, `\"`, -1), suffix)
+ }
+}
+
+func escapeForTextSelector(text interface{}, exact bool) string {
+ switch text := text.(type) {
+ case *regexp.Regexp:
+ return escapeRegexForSelector(text)
+ default:
+ if exact {
+ return fmt.Sprintf(`%ss`, escapeText(text.(string)))
+ }
+ return fmt.Sprintf(`%si`, escapeText(text.(string)))
+ }
+}
+
+func escapeRegexForSelector(re *regexp.Regexp) string {
+ pattern, flag := convertRegexp(re)
+ return fmt.Sprintf(`/%s/%s`, strings.ReplaceAll(pattern, `>>`, `\>\>`), flag)
+}
+
+func escapeText(s string) string {
+ builder := &strings.Builder{}
+ encoder := json.NewEncoder(builder)
+ encoder.SetEscapeHTML(false)
+ _ = encoder.Encode(s)
+ return strings.TrimSpace(builder.String())
+}
+
+func getByAltTextSelector(text interface{}, exact bool) string {
+ return getByAttributeTextSelector("alt", text, exact)
+}
+
+func getByAttributeTextSelector(attrName string, text interface{}, exact bool) string {
+ return fmt.Sprintf(`internal:attr=[%s=%s]`, attrName, escapeForAttributeSelector(text, exact))
+}
+
+func getByLabelSelector(text interface{}, exact bool) string {
+ return fmt.Sprintf(`internal:label=%s`, escapeForTextSelector(text, exact))
+}
+
+func getByPlaceholderSelector(text interface{}, exact bool) string {
+ return getByAttributeTextSelector("placeholder", text, exact)
+}
+
+func getByRoleSelector(role AriaRole, options ...LocatorGetByRoleOptions) string {
+ props := make(map[string]string)
+ if len(options) == 1 {
+ if options[0].Checked != nil {
+ props["checked"] = fmt.Sprintf("%t", *options[0].Checked)
+ }
+ if options[0].Disabled != nil {
+ props["disabled"] = fmt.Sprintf("%t", *options[0].Disabled)
+ }
+ if options[0].Selected != nil {
+ props["selected"] = fmt.Sprintf("%t", *options[0].Selected)
+ }
+ if options[0].Expanded != nil {
+ props["expanded"] = fmt.Sprintf("%t", *options[0].Expanded)
+ }
+ if options[0].IncludeHidden != nil {
+ props["include-hidden"] = fmt.Sprintf("%t", *options[0].IncludeHidden)
+ }
+ if options[0].Level != nil {
+ props["level"] = fmt.Sprintf("%d", *options[0].Level)
+ }
+ if options[0].Name != nil {
+ exact := false
+ if options[0].Exact != nil {
+ exact = *options[0].Exact
+ }
+ props["name"] = escapeForAttributeSelector(options[0].Name, exact)
+ }
+ if options[0].Pressed != nil {
+ props["pressed"] = fmt.Sprintf("%t", *options[0].Pressed)
+ }
+ }
+ propsStr := ""
+ for k, v := range props {
+ propsStr += "[" + k + "=" + v + "]"
+ }
+ return fmt.Sprintf("internal:role=%s%s", role, propsStr)
+}
+
+func getByTextSelector(text interface{}, exact bool) string {
+ return fmt.Sprintf(`internal:text=%s`, escapeForTextSelector(text, exact))
+}
+
+func getByTestIdSelector(testIdAttributeName string, testId interface{}) string {
+ return fmt.Sprintf(`internal:testid=[%s=%s]`, testIdAttributeName, escapeForAttributeSelector(testId, true))
+}
+
+func getByTitleSelector(text interface{}, exact bool) string {
+ return getByAttributeTextSelector("title", text, exact)
+}
+
+func getTestIdAttributeName() string {
+ return testIdAttributeName
+}
+
+func setTestIdAttributeName(name string) {
+ testIdAttributeName = name
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/network.go b/vendor/github.com/playwright-community/playwright-go/network.go
new file mode 100644
index 0000000..6f76fa5
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/network.go
@@ -0,0 +1,62 @@
+package playwright
+
+import (
+ "strings"
+)
+
+type rawHeaders struct {
+ headersArray []NameValue
+ headersMap map[string][]string
+}
+
+func (r *rawHeaders) Get(name string) string {
+ values := r.GetAll(name)
+ if len(values) == 0 {
+ return ""
+ }
+ sep := ", "
+ if strings.ToLower(name) == "set-cookie" {
+ sep = "\n"
+ }
+ return strings.Join(values, sep)
+}
+
+func (r *rawHeaders) GetAll(name string) []string {
+ name = strings.ToLower(name)
+ if _, ok := r.headersMap[name]; !ok {
+ return []string{}
+ }
+ return r.headersMap[name]
+}
+
+func (r *rawHeaders) Headers() map[string]string {
+ out := make(map[string]string)
+ for key := range r.headersMap {
+ out[key] = r.Get(key)
+ }
+ return out
+}
+
+func (r *rawHeaders) HeadersArray() []NameValue {
+ return r.headersArray
+}
+
+func newRawHeaders(headers interface{}) *rawHeaders {
+ r := &rawHeaders{}
+ r.headersArray = make([]NameValue, 0)
+ r.headersMap = make(map[string][]string)
+ for _, header := range headers.([]interface{}) {
+ entry := header.(map[string]interface{})
+ name := entry["name"].(string)
+ value := entry["value"].(string)
+ r.headersArray = append(r.headersArray, NameValue{
+ Name: name,
+ Value: value,
+ })
+ if _, ok := r.headersMap[strings.ToLower(name)]; !ok {
+ r.headersMap[strings.ToLower(name)] = make([]string, 0)
+ }
+ r.headersMap[strings.ToLower(name)] = append(r.headersMap[strings.ToLower(name)], value)
+ }
+ return r
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/objectFactory.go b/vendor/github.com/playwright-community/playwright-go/objectFactory.go
new file mode 100644
index 0000000..9474c54
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/objectFactory.go
@@ -0,0 +1,74 @@
+package playwright
+
+func createObjectFactory(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) interface{} {
+ switch objectType {
+ case "Android":
+ return nil
+ case "AndroidSocket":
+ return nil
+ case "AndroidDevice":
+ return nil
+ case "APIRequestContext":
+ return newAPIRequestContext(parent, objectType, guid, initializer)
+ case "Artifact":
+ return newArtifact(parent, objectType, guid, initializer)
+ case "BindingCall":
+ return newBindingCall(parent, objectType, guid, initializer)
+ case "Browser":
+ return newBrowser(parent, objectType, guid, initializer)
+ case "BrowserType":
+ return newBrowserType(parent, objectType, guid, initializer)
+ case "BrowserContext":
+ return newBrowserContext(parent, objectType, guid, initializer)
+ case "CDPSession":
+ return newCDPSession(parent, objectType, guid, initializer)
+ case "Dialog":
+ return newDialog(parent, objectType, guid, initializer)
+ case "Electron":
+ return nil
+ case "ElectronApplication":
+ return nil
+ case "ElementHandle":
+ return newElementHandle(parent, objectType, guid, initializer)
+ case "Frame":
+ return newFrame(parent, objectType, guid, initializer)
+ case "JSHandle":
+ return newJSHandle(parent, objectType, guid, initializer)
+ case "JsonPipe":
+ return newJsonPipe(parent, objectType, guid, initializer)
+ case "LocalUtils":
+ localUtils := newLocalUtils(parent, objectType, guid, initializer)
+ if localUtils.connection.localUtils == nil {
+ localUtils.connection.localUtils = localUtils
+ }
+ return localUtils
+ case "Page":
+ return newPage(parent, objectType, guid, initializer)
+ case "Playwright":
+ return newPlaywright(parent, objectType, guid, initializer)
+ case "Request":
+ return newRequest(parent, objectType, guid, initializer)
+ case "Response":
+ return newResponse(parent, objectType, guid, initializer)
+ case "Route":
+ return newRoute(parent, objectType, guid, initializer)
+ case "Selectors":
+ return newSelectorsOwner(parent, objectType, guid, initializer)
+ case "SocksSupport":
+ return nil
+ case "Stream":
+ return newStream(parent, objectType, guid, initializer)
+ case "Tracing":
+ return newTracing(parent, objectType, guid, initializer)
+ case "WebSocket":
+ return newWebsocket(parent, objectType, guid, initializer)
+ case "WebSocketRoute":
+ return newWebSocketRoute(parent, objectType, guid, initializer)
+ case "Worker":
+ return newWorker(parent, objectType, guid, initializer)
+ case "WritableStream":
+ return newWritableStream(parent, objectType, guid, initializer)
+ default:
+ panic(objectType)
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/page.go b/vendor/github.com/playwright-community/playwright-go/page.go
new file mode 100644
index 0000000..d4271a0
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/page.go
@@ -0,0 +1,1384 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "os"
+ "slices"
+ "sync"
+
+ "github.com/playwright-community/playwright-go/internal/safe"
+)
+
+type pageImpl struct {
+ channelOwner
+ isClosed bool
+ closedOrCrashed chan error
+ video *videoImpl
+ mouse *mouseImpl
+ keyboard *keyboardImpl
+ touchscreen *touchscreenImpl
+ timeoutSettings *timeoutSettings
+ browserContext *browserContextImpl
+ frames []Frame
+ workers []Worker
+ mainFrame Frame
+ routes []*routeHandlerEntry
+ webSocketRoutes []*webSocketRouteHandler
+ viewportSize *Size
+ ownedContext BrowserContext
+ bindings *safe.SyncMap[string, BindingCallFunction]
+ closeReason *string
+ closeWasCalled bool
+ harRouters []*harRouter
+ locatorHandlers map[float64]*locatorHandlerEntry
+}
+
+type locatorHandlerEntry struct {
+ locator *locatorImpl
+ handler func(Locator)
+ times *int
+}
+
+func (p *pageImpl) AddLocatorHandler(locator Locator, handler func(Locator), options ...PageAddLocatorHandlerOptions) error {
+ if locator == nil || handler == nil {
+ return errors.New("locator or handler must not be nil")
+ }
+ if locator.Err() != nil {
+ return locator.Err()
+ }
+
+ var option PageAddLocatorHandlerOptions
+ if len(options) == 1 {
+ option = options[0]
+ if option.Times != nil && *option.Times == 0 {
+ return nil
+ }
+ }
+
+ loc := locator.(*locatorImpl)
+ if loc.frame != p.mainFrame {
+ return errors.New("locator must belong to the main frame of this page")
+ }
+ uid, err := p.channel.Send("registerLocatorHandler", map[string]any{
+ "selector": loc.selector,
+ "noWaitAfter": option.NoWaitAfter,
+ })
+ if err != nil {
+ return err
+ }
+ p.locatorHandlers[uid.(float64)] = &locatorHandlerEntry{locator: loc, handler: handler, times: option.Times}
+ return nil
+}
+
+func (p *pageImpl) onLocatorHandlerTriggered(uid float64) {
+ var remove *bool
+ handler, ok := p.locatorHandlers[uid]
+ if !ok {
+ return
+ }
+ if handler.times != nil {
+ *handler.times--
+ if *handler.times == 0 {
+ remove = Bool(true)
+ }
+ }
+ defer func() {
+ if remove != nil && *remove {
+ delete(p.locatorHandlers, uid)
+ }
+ _, _ = p.connection.WrapAPICall(func() (interface{}, error) {
+ _, err := p.channel.Send("resolveLocatorHandlerNoReply", map[string]any{
+ "uid": uid,
+ "remove": remove,
+ })
+ return nil, err
+ }, true)
+ }()
+
+ handler.handler(handler.locator)
+}
+
+func (p *pageImpl) RemoveLocatorHandler(locator Locator) error {
+ for uid := range p.locatorHandlers {
+ if p.locatorHandlers[uid].locator.equals(locator) {
+ delete(p.locatorHandlers, uid)
+ p.channel.SendNoReply("unregisterLocatorHandler", map[string]any{
+ "uid": uid,
+ })
+ return nil
+ }
+ }
+ return nil
+}
+
+func (p *pageImpl) Context() BrowserContext {
+ return p.browserContext
+}
+
+func (b *pageImpl) Clock() Clock {
+ return b.browserContext.clock
+}
+
+func (p *pageImpl) Close(options ...PageCloseOptions) error {
+ if len(options) == 1 {
+ p.closeReason = options[0].Reason
+ }
+ p.closeWasCalled = true
+ _, err := p.channel.Send("close", options)
+ if err == nil && p.ownedContext != nil {
+ err = p.ownedContext.Close()
+ }
+ if errors.Is(err, ErrTargetClosed) || (len(options) == 1 && options[0].RunBeforeUnload != nil && *(options[0].RunBeforeUnload)) {
+ return nil
+ }
+ return err
+}
+
+func (p *pageImpl) InnerText(selector string, options ...PageInnerTextOptions) (string, error) {
+ if len(options) == 1 {
+ return p.mainFrame.InnerText(selector, FrameInnerTextOptions(options[0]))
+ }
+ return p.mainFrame.InnerText(selector)
+}
+
+func (p *pageImpl) InnerHTML(selector string, options ...PageInnerHTMLOptions) (string, error) {
+ if len(options) == 1 {
+ return p.mainFrame.InnerHTML(selector, FrameInnerHTMLOptions(options[0]))
+ }
+ return p.mainFrame.InnerHTML(selector)
+}
+
+func (p *pageImpl) Opener() (Page, error) {
+ channel := p.initializer["opener"]
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ // not popup page or opener has been closed
+ return nil, nil
+ }
+ return channelOwner.(*pageImpl), nil
+}
+
+func (p *pageImpl) MainFrame() Frame {
+ return p.mainFrame
+}
+
+func (p *pageImpl) Frame(options ...PageFrameOptions) Frame {
+ option := PageFrameOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ var matcher *urlMatcher
+ if option.URL != nil {
+ matcher = newURLMatcher(option.URL, p.browserContext.options.BaseURL)
+ }
+
+ for _, f := range p.frames {
+ if option.Name != nil && f.Name() == *option.Name {
+ return f
+ }
+
+ if option.URL != nil && matcher != nil && matcher.Matches(f.URL()) {
+ return f
+ }
+ }
+
+ return nil
+}
+
+func (p *pageImpl) Frames() []Frame {
+ return p.frames
+}
+
+func (p *pageImpl) SetDefaultNavigationTimeout(timeout float64) {
+ p.timeoutSettings.SetDefaultNavigationTimeout(&timeout)
+ p.channel.SendNoReplyInternal("setDefaultNavigationTimeoutNoReply", map[string]interface{}{
+ "timeout": timeout,
+ })
+}
+
+func (p *pageImpl) SetDefaultTimeout(timeout float64) {
+ p.timeoutSettings.SetDefaultTimeout(&timeout)
+ p.channel.SendNoReplyInternal("setDefaultTimeoutNoReply", map[string]interface{}{
+ "timeout": timeout,
+ })
+}
+
+func (p *pageImpl) QuerySelector(selector string, options ...PageQuerySelectorOptions) (ElementHandle, error) {
+ if len(options) == 1 {
+ return p.mainFrame.QuerySelector(selector, FrameQuerySelectorOptions(options[0]))
+ }
+ return p.mainFrame.QuerySelector(selector)
+}
+
+func (p *pageImpl) QuerySelectorAll(selector string) ([]ElementHandle, error) {
+ return p.mainFrame.QuerySelectorAll(selector)
+}
+
+func (p *pageImpl) WaitForSelector(selector string, options ...PageWaitForSelectorOptions) (ElementHandle, error) {
+ if len(options) == 1 {
+ return p.mainFrame.WaitForSelector(selector, FrameWaitForSelectorOptions(options[0]))
+ }
+ return p.mainFrame.WaitForSelector(selector)
+}
+
+func (p *pageImpl) DispatchEvent(selector string, typ string, eventInit interface{}, options ...PageDispatchEventOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.DispatchEvent(selector, typ, eventInit, FrameDispatchEventOptions(options[0]))
+ }
+ return p.mainFrame.DispatchEvent(selector, typ, eventInit)
+}
+
+func (p *pageImpl) Evaluate(expression string, arg ...interface{}) (interface{}, error) {
+ return p.mainFrame.Evaluate(expression, arg...)
+}
+
+func (p *pageImpl) EvaluateHandle(expression string, arg ...interface{}) (JSHandle, error) {
+ return p.mainFrame.EvaluateHandle(expression, arg...)
+}
+
+func (p *pageImpl) EvalOnSelector(selector string, expression string, arg interface{}, options ...PageEvalOnSelectorOptions) (interface{}, error) {
+ if len(options) == 1 {
+ return p.mainFrame.EvalOnSelector(selector, expression, arg, FrameEvalOnSelectorOptions(options[0]))
+ }
+ return p.mainFrame.EvalOnSelector(selector, expression, arg)
+}
+
+func (p *pageImpl) EvalOnSelectorAll(selector string, expression string, arg ...interface{}) (interface{}, error) {
+ return p.mainFrame.EvalOnSelectorAll(selector, expression, arg...)
+}
+
+func (p *pageImpl) AddScriptTag(options PageAddScriptTagOptions) (ElementHandle, error) {
+ return p.mainFrame.AddScriptTag(FrameAddScriptTagOptions(options))
+}
+
+func (p *pageImpl) AddStyleTag(options PageAddStyleTagOptions) (ElementHandle, error) {
+ return p.mainFrame.AddStyleTag(FrameAddStyleTagOptions(options))
+}
+
+func (p *pageImpl) SetExtraHTTPHeaders(headers map[string]string) error {
+ _, err := p.channel.Send("setExtraHTTPHeaders", map[string]interface{}{
+ "headers": serializeMapToNameAndValue(headers),
+ })
+ return err
+}
+
+func (p *pageImpl) URL() string {
+ return p.mainFrame.URL()
+}
+
+func (p *pageImpl) Unroute(url interface{}, handlers ...routeHandler) error {
+ p.Lock()
+ defer p.Unlock()
+
+ removed, remaining, err := unroute(p.routes, url, handlers...)
+ if err != nil {
+ return err
+ }
+ return p.unrouteInternal(removed, remaining, UnrouteBehaviorDefault)
+}
+
+func (p *pageImpl) unrouteInternal(removed []*routeHandlerEntry, remaining []*routeHandlerEntry, behavior *UnrouteBehavior) error {
+ p.routes = remaining
+ err := p.updateInterceptionPatterns()
+ if err != nil {
+ return err
+ }
+ 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
+}
+
+func (p *pageImpl) disposeHarRouters() {
+ for _, router := range p.harRouters {
+ router.dispose()
+ }
+ p.harRouters = make([]*harRouter, 0)
+}
+
+func (p *pageImpl) UnrouteAll(options ...PageUnrouteAllOptions) error {
+ var behavior *UnrouteBehavior
+ if len(options) == 1 {
+ behavior = options[0].Behavior
+ }
+ p.Lock()
+ defer p.Unlock()
+ defer p.disposeHarRouters()
+ return p.unrouteInternal(p.routes, []*routeHandlerEntry{}, behavior)
+}
+
+func (p *pageImpl) Content() (string, error) {
+ return p.mainFrame.Content()
+}
+
+func (p *pageImpl) SetContent(html string, options ...PageSetContentOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.SetContent(html, FrameSetContentOptions(options[0]))
+ }
+ return p.mainFrame.SetContent(html)
+}
+
+func (p *pageImpl) Goto(url string, options ...PageGotoOptions) (Response, error) {
+ if len(options) == 1 {
+ return p.mainFrame.Goto(url, FrameGotoOptions(options[0]))
+ }
+ return p.mainFrame.Goto(url)
+}
+
+func (p *pageImpl) Reload(options ...PageReloadOptions) (Response, error) {
+ channel, err := p.channel.Send("reload", options)
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ return nil, nil
+ }
+ return channelOwner.(*responseImpl), nil
+}
+
+func (p *pageImpl) WaitForLoadState(options ...PageWaitForLoadStateOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.WaitForLoadState(FrameWaitForLoadStateOptions(options[0]))
+ }
+ return p.mainFrame.WaitForLoadState()
+}
+
+func (p *pageImpl) GoBack(options ...PageGoBackOptions) (Response, error) {
+ channel, err := p.channel.Send("goBack", options)
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ // can not go back
+ return nil, nil
+ }
+ return channelOwner.(*responseImpl), nil
+}
+
+func (p *pageImpl) GoForward(options ...PageGoForwardOptions) (Response, error) {
+ channel, err := p.channel.Send("goForward", options)
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ // can not go forward
+ return nil, nil
+ }
+ return channelOwner.(*responseImpl), nil
+}
+
+func (p *pageImpl) EmulateMedia(options ...PageEmulateMediaOptions) error {
+ _, err := p.channel.Send("emulateMedia", options)
+ if err != nil {
+ return err
+ }
+ return err
+}
+
+func (p *pageImpl) SetViewportSize(width, height int) error {
+ _, err := p.channel.Send("setViewportSize", map[string]interface{}{
+ "viewportSize": map[string]interface{}{
+ "width": width,
+ "height": height,
+ },
+ })
+ if err != nil {
+ return err
+ }
+ p.viewportSize.Width = width
+ p.viewportSize.Height = height
+ return nil
+}
+
+func (p *pageImpl) ViewportSize() *Size {
+ return p.viewportSize
+}
+
+func (p *pageImpl) BringToFront() error {
+ _, err := p.channel.Send("bringToFront")
+ return err
+}
+
+func (p *pageImpl) Type(selector, text string, options ...PageTypeOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Type(selector, text, FrameTypeOptions(options[0]))
+ }
+ return p.mainFrame.Type(selector, text)
+}
+
+func (p *pageImpl) Fill(selector, text string, options ...PageFillOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Fill(selector, text, FrameFillOptions(options[0]))
+ }
+ return p.mainFrame.Fill(selector, text)
+}
+
+func (p *pageImpl) Press(selector, key string, options ...PagePressOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Press(selector, key, FramePressOptions(options[0]))
+ }
+ return p.mainFrame.Press(selector, key)
+}
+
+func (p *pageImpl) Title() (string, error) {
+ return p.mainFrame.Title()
+}
+
+func (p *pageImpl) Workers() []Worker {
+ return p.workers
+}
+
+func (p *pageImpl) Request() APIRequestContext {
+ return p.Context().Request()
+}
+
+func (p *pageImpl) Screenshot(options ...PageScreenshotOptions) ([]byte, error) {
+ var path *string
+ overrides := map[string]interface{}{}
+ if len(options) == 1 {
+ path = options[0].Path
+ options[0].Path = nil
+ if options[0].Mask != nil {
+ masks := make([]map[string]interface{}, 0)
+ for _, m := range options[0].Mask {
+ if m.Err() != nil { // ErrLocatorNotSameFrame
+ return nil, m.Err()
+ }
+ l, ok := m.(*locatorImpl)
+ if ok {
+ masks = append(masks, map[string]interface{}{
+ "selector": l.selector,
+ "frame": l.frame.channel,
+ })
+ }
+ }
+ overrides["mask"] = masks
+ }
+ }
+ data, err := p.channel.Send("screenshot", options, overrides)
+ if err != nil {
+ 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, 0o644); err != nil {
+ return nil, err
+ }
+ }
+ return image, nil
+}
+
+func (p *pageImpl) PDF(options ...PagePdfOptions) ([]byte, error) {
+ var path *string
+ if len(options) == 1 {
+ path = options[0].Path
+ }
+ data, err := p.channel.Send("pdf", options)
+ if err != nil {
+ return nil, err
+ }
+ pdf, 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, pdf, 0o644); err != nil {
+ return nil, err
+ }
+ }
+ return pdf, nil
+}
+
+func (p *pageImpl) Click(selector string, options ...PageClickOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Click(selector, FrameClickOptions(options[0]))
+ }
+ return p.mainFrame.Click(selector)
+}
+
+func (p *pageImpl) WaitForEvent(event string, options ...PageWaitForEventOptions) (interface{}, error) {
+ return p.waiterForEvent(event, options...).Wait()
+}
+
+func (p *pageImpl) waiterForEvent(event string, options ...PageWaitForEventOptions) *waiter {
+ timeout := p.timeoutSettings.Timeout()
+ var predicate interface{} = nil
+ if len(options) == 1 {
+ if options[0].Timeout != nil {
+ timeout = *options[0].Timeout
+ }
+ predicate = options[0].Predicate
+ }
+ waiter := newWaiter().WithTimeout(timeout)
+ waiter.RejectOnEvent(p, "close", p.closeErrorWithReason())
+ waiter.RejectOnEvent(p, "crash", errors.New("page crashed"))
+ return waiter.WaitForEvent(p, event, predicate)
+}
+
+func (p *pageImpl) waiterForRequest(url interface{}, options ...PageExpectRequestOptions) *waiter {
+ option := PageExpectRequestOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ if option.Timeout == nil {
+ option.Timeout = Float(p.timeoutSettings.Timeout())
+ }
+ var matcher *urlMatcher
+ if url != nil {
+ matcher = newURLMatcher(url, p.browserContext.options.BaseURL)
+ }
+ predicate := func(req *requestImpl) bool {
+ if matcher != nil {
+ return matcher.Matches(req.URL())
+ }
+ return true
+ }
+
+ waiter := newWaiter().WithTimeout(*option.Timeout)
+ return waiter.WaitForEvent(p, "request", predicate)
+}
+
+func (p *pageImpl) waiterForResponse(url interface{}, options ...PageExpectResponseOptions) *waiter {
+ option := PageExpectResponseOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ if option.Timeout == nil {
+ option.Timeout = Float(p.timeoutSettings.Timeout())
+ }
+ var matcher *urlMatcher
+ if url != nil {
+ matcher = newURLMatcher(url, p.browserContext.options.BaseURL)
+ }
+ predicate := func(req *responseImpl) bool {
+ if matcher != nil {
+ return matcher.Matches(req.URL())
+ }
+ return true
+ }
+
+ waiter := newWaiter().WithTimeout(*option.Timeout)
+ return waiter.WaitForEvent(p, "response", predicate)
+}
+
+func (p *pageImpl) ExpectEvent(event string, cb func() error, options ...PageExpectEventOptions) (interface{}, error) {
+ if len(options) == 1 {
+ return p.waiterForEvent(event, PageWaitForEventOptions(options[0])).RunAndWait(cb)
+ }
+ return p.waiterForEvent(event).RunAndWait(cb)
+}
+
+func (p *pageImpl) ExpectNavigation(cb func() error, options ...PageExpectNavigationOptions) (Response, error) {
+ if len(options) == 1 {
+ return p.mainFrame.ExpectNavigation(cb, FrameExpectNavigationOptions(options[0]))
+ }
+ return p.mainFrame.ExpectNavigation(cb)
+}
+
+func (p *pageImpl) ExpectConsoleMessage(cb func() error, options ...PageExpectConsoleMessageOptions) (ConsoleMessage, error) {
+ option := PageWaitForEventOptions{}
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ option.Predicate = options[0].Predicate
+ }
+ ret, err := p.waiterForEvent("console", option).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*consoleMessageImpl), err
+}
+
+func (p *pageImpl) ExpectDownload(cb func() error, options ...PageExpectDownloadOptions) (Download, error) {
+ option := PageWaitForEventOptions{}
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ option.Predicate = options[0].Predicate
+ }
+ ret, err := p.waiterForEvent("download", option).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*downloadImpl), err
+}
+
+func (p *pageImpl) ExpectFileChooser(cb func() error, options ...PageExpectFileChooserOptions) (FileChooser, error) {
+ option := PageWaitForEventOptions{}
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ option.Predicate = options[0].Predicate
+ }
+ ret, err := p.waiterForEvent("filechooser", option).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*fileChooserImpl), err
+}
+
+func (p *pageImpl) ExpectPopup(cb func() error, options ...PageExpectPopupOptions) (Page, error) {
+ option := PageWaitForEventOptions{}
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ option.Predicate = options[0].Predicate
+ }
+ ret, err := p.waiterForEvent("popup", option).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*pageImpl), err
+}
+
+func (p *pageImpl) ExpectResponse(url interface{}, cb func() error, options ...PageExpectResponseOptions) (Response, error) {
+ ret, err := p.waiterForResponse(url, options...).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*responseImpl), err
+}
+
+func (p *pageImpl) ExpectRequest(url interface{}, cb func() error, options ...PageExpectRequestOptions) (Request, error) {
+ ret, err := p.waiterForRequest(url, options...).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*requestImpl), err
+}
+
+func (p *pageImpl) ExpectRequestFinished(cb func() error, options ...PageExpectRequestFinishedOptions) (Request, error) {
+ option := PageWaitForEventOptions{}
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ option.Predicate = options[0].Predicate
+ }
+ ret, err := p.waiterForEvent("requestfinished", option).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*requestImpl), err
+}
+
+func (p *pageImpl) ExpectWebSocket(cb func() error, options ...PageExpectWebSocketOptions) (WebSocket, error) {
+ option := PageWaitForEventOptions{}
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ option.Predicate = options[0].Predicate
+ }
+ ret, err := p.waiterForEvent("websocket", option).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*webSocketImpl), err
+}
+
+func (p *pageImpl) ExpectWorker(cb func() error, options ...PageExpectWorkerOptions) (Worker, error) {
+ option := PageWaitForEventOptions{}
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ option.Predicate = options[0].Predicate
+ }
+ ret, err := p.waiterForEvent("worker", option).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*workerImpl), err
+}
+
+func (p *pageImpl) Route(url interface{}, handler routeHandler, times ...int) error {
+ p.Lock()
+ defer p.Unlock()
+ p.routes = slices.Insert(p.routes, 0, newRouteHandlerEntry(newURLMatcher(url, p.browserContext.options.BaseURL), handler, times...))
+ return p.updateInterceptionPatterns()
+}
+
+func (p *pageImpl) GetAttribute(selector string, name string, options ...PageGetAttributeOptions) (string, error) {
+ if len(options) == 1 {
+ return p.mainFrame.GetAttribute(selector, name, FrameGetAttributeOptions(options[0]))
+ }
+ return p.mainFrame.GetAttribute(selector, name)
+}
+
+func (p *pageImpl) Hover(selector string, options ...PageHoverOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Hover(selector, FrameHoverOptions(options[0]))
+ }
+ return p.mainFrame.Hover(selector)
+}
+
+func (p *pageImpl) IsClosed() bool {
+ return p.isClosed
+}
+
+func (p *pageImpl) AddInitScript(script Script) error {
+ var source string
+ if script.Content != nil {
+ source = *script.Content
+ }
+ if script.Path != nil {
+ content, err := os.ReadFile(*script.Path)
+ if err != nil {
+ return err
+ }
+ source = string(content)
+ }
+ _, err := p.channel.Send("addInitScript", map[string]interface{}{
+ "source": source,
+ })
+ return err
+}
+
+func (p *pageImpl) Keyboard() Keyboard {
+ return p.keyboard
+}
+
+func (p *pageImpl) Mouse() Mouse {
+ return p.mouse
+}
+
+func (p *pageImpl) RouteFromHAR(har string, options ...PageRouteFromHAROptions) error {
+ opt := PageRouteFromHAROptions{}
+ if len(options) == 1 {
+ opt = options[0]
+ }
+ if opt.Update != nil && *opt.Update {
+ return p.browserContext.recordIntoHar(har, browserContextRecordIntoHarOptions{
+ Page: p,
+ URL: opt.URL,
+ })
+ }
+ notFound := opt.NotFound
+ if notFound == nil {
+ notFound = HarNotFoundAbort
+ }
+ router := newHarRouter(p.connection.localUtils, har, *notFound, opt.URL)
+ p.harRouters = append(p.harRouters, router)
+ return router.addPageRoute(p)
+}
+
+func (p *pageImpl) Touchscreen() Touchscreen {
+ return p.touchscreen
+}
+
+func newPage(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *pageImpl {
+ viewportSize := &Size{}
+ if _, ok := initializer["viewportSize"].(map[string]interface{}); ok {
+ viewportSize.Height = int(initializer["viewportSize"].(map[string]interface{})["height"].(float64))
+ viewportSize.Width = int(initializer["viewportSize"].(map[string]interface{})["width"].(float64))
+ }
+ bt := &pageImpl{
+ workers: make([]Worker, 0),
+ routes: make([]*routeHandlerEntry, 0),
+ bindings: safe.NewSyncMap[string, BindingCallFunction](),
+ viewportSize: viewportSize,
+ harRouters: make([]*harRouter, 0),
+ locatorHandlers: make(map[float64]*locatorHandlerEntry, 0),
+ }
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ bt.browserContext = fromChannel(parent.channel).(*browserContextImpl)
+ bt.timeoutSettings = newTimeoutSettings(bt.browserContext.timeoutSettings)
+ mainframe := fromChannel(initializer["mainFrame"]).(*frameImpl)
+ mainframe.page = bt
+ bt.mainFrame = mainframe
+ bt.frames = []Frame{mainframe}
+ bt.mouse = newMouse(bt.channel)
+ bt.keyboard = newKeyboard(bt.channel)
+ bt.touchscreen = newTouchscreen(bt.channel)
+ bt.channel.On("bindingCall", func(params map[string]interface{}) {
+ bt.onBinding(fromChannel(params["binding"]).(*bindingCallImpl))
+ })
+ bt.channel.On("close", bt.onClose)
+ bt.channel.On("crash", func() {
+ bt.Emit("crash", bt)
+ })
+ bt.channel.On("domcontentloaded", func() {
+ bt.Emit("domcontentloaded", bt)
+ })
+ bt.channel.On("fileChooser", func(ev map[string]interface{}) {
+ bt.Emit("filechooser", newFileChooser(bt, fromChannel(ev["element"]).(*elementHandleImpl), ev["isMultiple"].(bool)))
+ })
+ bt.channel.On("frameAttached", func(ev map[string]interface{}) {
+ bt.onFrameAttached(fromChannel(ev["frame"]).(*frameImpl))
+ })
+ bt.channel.On("frameDetached", func(ev map[string]interface{}) {
+ bt.onFrameDetached(fromChannel(ev["frame"]).(*frameImpl))
+ })
+ bt.channel.On("locatorHandlerTriggered", func(ev map[string]interface{}) {
+ bt.channel.CreateTask(func() {
+ bt.onLocatorHandlerTriggered(ev["uid"].(float64))
+ })
+ })
+ bt.channel.On(
+ "load", func(ev map[string]interface{}) {
+ bt.Emit("load", bt)
+ },
+ )
+ bt.channel.On("popup", func(ev map[string]interface{}) {
+ bt.Emit("popup", fromChannel(ev["page"]).(*pageImpl))
+ })
+ bt.channel.On("route", func(ev map[string]interface{}) {
+ bt.channel.CreateTask(func() {
+ bt.onRoute(fromChannel(ev["route"]).(*routeImpl))
+ })
+ })
+ bt.channel.On("download", func(ev map[string]interface{}) {
+ url := ev["url"].(string)
+ suggestedFilename := ev["suggestedFilename"].(string)
+ artifact := fromChannel(ev["artifact"]).(*artifactImpl)
+ bt.Emit("download", newDownload(bt, url, suggestedFilename, artifact))
+ })
+ bt.channel.On("video", func(params map[string]interface{}) {
+ artifact := fromChannel(params["artifact"]).(*artifactImpl)
+ bt.Video().(*videoImpl).artifactReady(artifact)
+ })
+ bt.channel.On("webSocket", func(ev map[string]interface{}) {
+ bt.Emit("websocket", fromChannel(ev["webSocket"]).(*webSocketImpl))
+ })
+ bt.channel.On("webSocketRoute", func(ev map[string]interface{}) {
+ bt.channel.CreateTask(func() {
+ bt.onWebSocketRoute(fromChannel(ev["webSocketRoute"]).(*webSocketRouteImpl))
+ })
+ })
+
+ bt.channel.On("worker", func(ev map[string]interface{}) {
+ bt.onWorker(fromChannel(ev["worker"]).(*workerImpl))
+ })
+ bt.closedOrCrashed = make(chan error, 1)
+ bt.OnClose(func(Page) {
+ select {
+ case bt.closedOrCrashed <- bt.closeErrorWithReason():
+ default:
+ }
+ })
+ bt.OnCrash(func(Page) {
+ select {
+ case bt.closedOrCrashed <- ErrTargetClosed:
+ default:
+ }
+ })
+ bt.setEventSubscriptionMapping(map[string]string{
+ "console": "console",
+ "dialog": "dialog",
+ "request": "request",
+ "response": "response",
+ "requestfinished": "requestFinished",
+ "responsefailed": "responseFailed",
+ "filechooser": "fileChooser",
+ })
+
+ return bt
+}
+
+func (p *pageImpl) closeErrorWithReason() error {
+ if p.closeReason != nil {
+ return targetClosedError(p.closeReason)
+ }
+ return targetClosedError(p.browserContext.effectiveCloseReason())
+}
+
+func (p *pageImpl) onBinding(binding *bindingCallImpl) {
+ function, ok := p.bindings.Load(binding.initializer["name"].(string))
+ if !ok || function == nil {
+ return
+ }
+ go binding.Call(function)
+}
+
+func (p *pageImpl) onFrameAttached(frame *frameImpl) {
+ frame.page = p
+ p.frames = append(p.frames, frame)
+ p.Emit("frameattached", frame)
+}
+
+func (p *pageImpl) onFrameDetached(frame *frameImpl) {
+ frame.detached = true
+ frames := make([]Frame, 0)
+ for i := 0; i < len(p.frames); i++ {
+ if p.frames[i] != frame {
+ frames = append(frames, frame)
+ }
+ }
+ if len(frames) != len(p.frames) {
+ p.frames = frames
+ }
+ p.Emit("framedetached", frame)
+}
+
+func (p *pageImpl) onRoute(route *routeImpl) {
+ p.Lock()
+ route.context = p.browserContext
+ routes := make([]*routeHandlerEntry, len(p.routes))
+ copy(routes, p.routes)
+ p.Unlock()
+
+ checkInterceptionIfNeeded := func() {
+ p.Lock()
+ defer p.Unlock()
+ if len(p.routes) == 0 {
+ _, err := p.connection.WrapAPICall(func() (interface{}, error) {
+ err := p.updateInterceptionPatterns()
+ return nil, err
+ }, true)
+ if err != nil {
+ logger.Error("could not update interception patterns", "error", err)
+ }
+ }
+ }
+
+ url := route.Request().URL()
+ for _, handlerEntry := range routes {
+ // If the page was closed we stall all requests right away.
+ if p.closeWasCalled || p.browserContext.closeWasCalled {
+ return
+ }
+ if !handlerEntry.Matches(url) {
+ continue
+ }
+ if !slices.ContainsFunc(p.routes, func(entry *routeHandlerEntry) bool {
+ return entry == handlerEntry
+ }) {
+ continue
+ }
+ if handlerEntry.WillExceed() {
+ p.routes = slices.DeleteFunc(p.routes, func(rhe *routeHandlerEntry) bool {
+ return rhe == handlerEntry
+ })
+ }
+ handled := handlerEntry.Handle(route)
+ checkInterceptionIfNeeded()
+
+ if <-handled {
+ return
+ }
+ }
+ p.browserContext.onRoute(route)
+}
+
+func (p *pageImpl) updateInterceptionPatterns() error {
+ patterns := prepareInterceptionPatterns(p.routes)
+ _, err := p.channel.Send("setNetworkInterceptionPatterns", map[string]interface{}{
+ "patterns": patterns,
+ })
+ return err
+}
+
+func (p *pageImpl) onWorker(worker *workerImpl) {
+ p.workers = append(p.workers, worker)
+ worker.page = p
+ p.Emit("worker", worker)
+}
+
+func (p *pageImpl) onClose() {
+ p.isClosed = true
+ newPages := []Page{}
+ newBackgoundPages := []Page{}
+ if p.browserContext != nil {
+ p.browserContext.Lock()
+ for _, page := range p.browserContext.pages {
+ if page != p {
+ newPages = append(newPages, page)
+ }
+ }
+ for _, page := range p.browserContext.backgroundPages {
+ if page != p {
+ newBackgoundPages = append(newBackgoundPages, page)
+ }
+ }
+ p.browserContext.pages = newPages
+ p.browserContext.backgroundPages = newBackgoundPages
+ p.browserContext.Unlock()
+ }
+ p.disposeHarRouters()
+ p.Emit("close", p)
+}
+
+func (p *pageImpl) SetInputFiles(selector string, files interface{}, options ...PageSetInputFilesOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.SetInputFiles(selector, files, FrameSetInputFilesOptions(options[0]))
+ }
+ return p.mainFrame.SetInputFiles(selector, files)
+}
+
+func (p *pageImpl) Check(selector string, options ...PageCheckOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Check(selector, FrameCheckOptions(options[0]))
+ }
+ return p.mainFrame.Check(selector)
+}
+
+func (p *pageImpl) Uncheck(selector string, options ...PageUncheckOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Uncheck(selector, FrameUncheckOptions(options[0]))
+ }
+ return p.mainFrame.Uncheck(selector)
+}
+
+func (p *pageImpl) WaitForTimeout(timeout float64) {
+ p.mainFrame.WaitForTimeout(timeout)
+}
+
+func (p *pageImpl) WaitForFunction(expression string, arg interface{}, options ...PageWaitForFunctionOptions) (JSHandle, error) {
+ if len(options) == 1 {
+ return p.mainFrame.WaitForFunction(expression, arg, FrameWaitForFunctionOptions(options[0]))
+ }
+ return p.mainFrame.WaitForFunction(expression, arg)
+}
+
+func (p *pageImpl) Dblclick(expression string, options ...PageDblclickOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Dblclick(expression, FrameDblclickOptions(options[0]))
+ }
+ return p.mainFrame.Dblclick(expression)
+}
+
+func (p *pageImpl) Focus(expression string, options ...PageFocusOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Focus(expression, FrameFocusOptions(options[0]))
+ }
+ return p.mainFrame.Focus(expression)
+}
+
+func (p *pageImpl) TextContent(selector string, options ...PageTextContentOptions) (string, error) {
+ if len(options) == 1 {
+ return p.mainFrame.TextContent(selector, FrameTextContentOptions(options[0]))
+ }
+ return p.mainFrame.TextContent(selector)
+}
+
+func (p *pageImpl) Video() Video {
+ p.Lock()
+ defer p.Unlock()
+
+ if p.video == nil {
+ p.video = newVideo(p)
+ }
+ return p.video
+}
+
+func (p *pageImpl) Tap(selector string, options ...PageTapOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Tap(selector, FrameTapOptions(options[0]))
+ }
+ return p.mainFrame.Tap(selector)
+}
+
+func (p *pageImpl) ExposeFunction(name string, binding ExposedFunction) error {
+ return p.ExposeBinding(name, func(source *BindingSource, args ...interface{}) interface{} {
+ return binding(args...)
+ })
+}
+
+func (p *pageImpl) ExposeBinding(name string, binding BindingCallFunction, handle ...bool) error {
+ needsHandle := false
+ if len(handle) == 1 {
+ needsHandle = handle[0]
+ }
+ if _, ok := p.bindings.Load(name); ok {
+ return fmt.Errorf("Function '%s' has been already registered", name)
+ }
+ if _, ok := p.browserContext.bindings.Load(name); ok {
+ return fmt.Errorf("Function '%s' has been already registered in the browser context", name)
+ }
+ _, err := p.channel.Send("exposeBinding", map[string]interface{}{
+ "name": name,
+ "needsHandle": needsHandle,
+ })
+ if err != nil {
+ return err
+ }
+ p.bindings.Store(name, binding)
+ return nil
+}
+
+func (p *pageImpl) SelectOption(selector string, values SelectOptionValues, options ...PageSelectOptionOptions) ([]string, error) {
+ if len(options) == 1 {
+ return p.mainFrame.SelectOption(selector, values, FrameSelectOptionOptions(options[0]))
+ }
+ return p.mainFrame.SelectOption(selector, values)
+}
+
+func (p *pageImpl) IsChecked(selector string, options ...PageIsCheckedOptions) (bool, error) {
+ if len(options) == 1 {
+ return p.mainFrame.IsChecked(selector, FrameIsCheckedOptions(options[0]))
+ }
+ return p.mainFrame.IsChecked(selector)
+}
+
+func (p *pageImpl) IsDisabled(selector string, options ...PageIsDisabledOptions) (bool, error) {
+ if len(options) == 1 {
+ return p.mainFrame.IsDisabled(selector, FrameIsDisabledOptions(options[0]))
+ }
+ return p.mainFrame.IsDisabled(selector)
+}
+
+func (p *pageImpl) IsEditable(selector string, options ...PageIsEditableOptions) (bool, error) {
+ if len(options) == 1 {
+ return p.mainFrame.IsEditable(selector, FrameIsEditableOptions(options[0]))
+ }
+ return p.mainFrame.IsEditable(selector)
+}
+
+func (p *pageImpl) IsEnabled(selector string, options ...PageIsEnabledOptions) (bool, error) {
+ if len(options) == 1 {
+ return p.mainFrame.IsEnabled(selector, FrameIsEnabledOptions(options[0]))
+ }
+ return p.mainFrame.IsEnabled(selector)
+}
+
+func (p *pageImpl) IsHidden(selector string, options ...PageIsHiddenOptions) (bool, error) {
+ if len(options) == 1 {
+ return p.mainFrame.IsHidden(selector, FrameIsHiddenOptions(options[0]))
+ }
+ return p.mainFrame.IsHidden(selector)
+}
+
+func (p *pageImpl) IsVisible(selector string, options ...PageIsVisibleOptions) (bool, error) {
+ if len(options) == 1 {
+ return p.mainFrame.IsVisible(selector, FrameIsVisibleOptions(options[0]))
+ }
+ return p.mainFrame.IsVisible(selector)
+}
+
+func (p *pageImpl) DragAndDrop(source, target string, options ...PageDragAndDropOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.DragAndDrop(source, target, FrameDragAndDropOptions(options[0]))
+ }
+ return p.mainFrame.DragAndDrop(source, target)
+}
+
+func (p *pageImpl) Pause() (err error) {
+ defaultNavigationTimout := p.browserContext.timeoutSettings.DefaultNavigationTimeout()
+ defaultTimeout := p.browserContext.timeoutSettings.DefaultTimeout()
+ p.browserContext.SetDefaultNavigationTimeout(0)
+ p.browserContext.SetDefaultTimeout(0)
+ select {
+ case err = <-p.closedOrCrashed:
+ case err = <-p.browserContext.pause():
+ }
+ if err != nil {
+ return err
+ }
+ p.browserContext.setDefaultNavigationTimeoutImpl(defaultNavigationTimout)
+ p.browserContext.setDefaultTimeoutImpl(defaultTimeout)
+ return
+}
+
+func (p *pageImpl) InputValue(selector string, options ...PageInputValueOptions) (string, error) {
+ if len(options) == 1 {
+ return p.mainFrame.InputValue(selector, FrameInputValueOptions(options[0]))
+ }
+ return p.mainFrame.InputValue(selector)
+}
+
+func (p *pageImpl) WaitForURL(url interface{}, options ...PageWaitForURLOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.WaitForURL(url, FrameWaitForURLOptions(options[0]))
+ }
+ return p.mainFrame.WaitForURL(url)
+}
+
+func (p *pageImpl) SetChecked(selector string, checked bool, options ...PageSetCheckedOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.SetChecked(selector, checked, FrameSetCheckedOptions(options[0]))
+ }
+ return p.mainFrame.SetChecked(selector, checked)
+}
+
+func (p *pageImpl) Locator(selector string, options ...PageLocatorOptions) Locator {
+ var option FrameLocatorOptions
+ if len(options) == 1 {
+ option = FrameLocatorOptions(options[0])
+ }
+ return p.mainFrame.Locator(selector, option)
+}
+
+func (p *pageImpl) GetByAltText(text interface{}, options ...PageGetByAltTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return p.Locator(getByAltTextSelector(text, exact))
+}
+
+func (p *pageImpl) GetByLabel(text interface{}, options ...PageGetByLabelOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return p.Locator(getByLabelSelector(text, exact))
+}
+
+func (p *pageImpl) GetByPlaceholder(text interface{}, options ...PageGetByPlaceholderOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return p.Locator(getByPlaceholderSelector(text, exact))
+}
+
+func (p *pageImpl) GetByRole(role AriaRole, options ...PageGetByRoleOptions) Locator {
+ if len(options) == 1 {
+ return p.Locator(getByRoleSelector(role, LocatorGetByRoleOptions(options[0])))
+ }
+ return p.Locator(getByRoleSelector(role))
+}
+
+func (p *pageImpl) GetByTestId(testId interface{}) Locator {
+ return p.Locator(getByTestIdSelector(getTestIdAttributeName(), testId))
+}
+
+func (p *pageImpl) GetByText(text interface{}, options ...PageGetByTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return p.Locator(getByTextSelector(text, exact))
+}
+
+func (p *pageImpl) GetByTitle(text interface{}, options ...PageGetByTitleOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return p.Locator(getByTitleSelector(text, exact))
+}
+
+func (p *pageImpl) FrameLocator(selector string) FrameLocator {
+ return p.mainFrame.FrameLocator(selector)
+}
+
+func (p *pageImpl) OnClose(fn func(Page)) {
+ p.On("close", fn)
+}
+
+func (p *pageImpl) OnConsole(fn func(ConsoleMessage)) {
+ p.On("console", fn)
+}
+
+func (p *pageImpl) OnCrash(fn func(Page)) {
+ p.On("crash", fn)
+}
+
+func (p *pageImpl) OnDialog(fn func(Dialog)) {
+ p.On("dialog", fn)
+}
+
+func (p *pageImpl) OnDOMContentLoaded(fn func(Page)) {
+ p.On("domcontentloaded", fn)
+}
+
+func (p *pageImpl) OnDownload(fn func(Download)) {
+ p.On("download", fn)
+}
+
+func (p *pageImpl) OnFileChooser(fn func(FileChooser)) {
+ p.On("filechooser", fn)
+}
+
+func (p *pageImpl) OnFrameAttached(fn func(Frame)) {
+ p.On("frameattached", fn)
+}
+
+func (p *pageImpl) OnFrameDetached(fn func(Frame)) {
+ p.On("framedetached", fn)
+}
+
+func (p *pageImpl) OnFrameNavigated(fn func(Frame)) {
+ p.On("framenavigated", fn)
+}
+
+func (p *pageImpl) OnLoad(fn func(Page)) {
+ p.On("load", fn)
+}
+
+func (p *pageImpl) OnPageError(fn func(error)) {
+ p.On("pageerror", fn)
+}
+
+func (p *pageImpl) OnPopup(fn func(Page)) {
+ p.On("popup", fn)
+}
+
+func (p *pageImpl) OnRequest(fn func(Request)) {
+ p.On("request", fn)
+}
+
+func (p *pageImpl) OnRequestFailed(fn func(Request)) {
+ p.On("requestfailed", fn)
+}
+
+func (p *pageImpl) OnRequestFinished(fn func(Request)) {
+ p.On("requestfinished", fn)
+}
+
+func (p *pageImpl) OnResponse(fn func(Response)) {
+ p.On("response", fn)
+}
+
+func (p *pageImpl) OnWebSocket(fn func(WebSocket)) {
+ p.On("websocket", fn)
+}
+
+func (p *pageImpl) OnWorker(fn func(Worker)) {
+ p.On("worker", fn)
+}
+
+func (p *pageImpl) RequestGC() error {
+ _, err := p.channel.Send("requestGC")
+ return err
+}
+
+func (p *pageImpl) RouteWebSocket(url interface{}, handler func(WebSocketRoute)) error {
+ p.Lock()
+ defer p.Unlock()
+ p.webSocketRoutes = slices.Insert(p.webSocketRoutes, 0, newWebSocketRouteHandler(newURLMatcher(url, p.browserContext.options.BaseURL, true), handler))
+
+ return p.updateWebSocketInterceptionPatterns()
+}
+
+func (p *pageImpl) onWebSocketRoute(wr WebSocketRoute) {
+ p.Lock()
+ index := slices.IndexFunc(p.webSocketRoutes, func(r *webSocketRouteHandler) bool {
+ return r.Matches(wr.URL())
+ })
+ if index == -1 {
+ p.Unlock()
+ p.browserContext.onWebSocketRoute(wr)
+ return
+ }
+ handler := p.webSocketRoutes[index]
+ p.Unlock()
+ handler.Handle(wr)
+}
+
+func (p *pageImpl) updateWebSocketInterceptionPatterns() error {
+ patterns := prepareWebSocketRouteHandlerInterceptionPatterns(p.webSocketRoutes)
+ _, err := p.channel.Send("setWebSocketInterceptionPatterns", map[string]interface{}{
+ "patterns": patterns,
+ })
+ return err
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/page_assertions.go b/vendor/github.com/playwright-community/playwright-go/page_assertions.go
new file mode 100644
index 0000000..43bd0dc
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/page_assertions.go
@@ -0,0 +1,70 @@
+package playwright
+
+import (
+ "net/url"
+ "path"
+)
+
+type pageAssertionsImpl struct {
+ assertionsBase
+ actualPage Page
+}
+
+func newPageAssertions(page Page, isNot bool, defaultTimeout *float64) *pageAssertionsImpl {
+ return &pageAssertionsImpl{
+ assertionsBase: assertionsBase{
+ actualLocator: page.Locator(":root"),
+ isNot: isNot,
+ defaultTimeout: defaultTimeout,
+ },
+ actualPage: page,
+ }
+}
+
+func (pa *pageAssertionsImpl) ToHaveTitle(titleOrRegExp interface{}, options ...PageAssertionsToHaveTitleOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ expectedValues, err := toExpectedTextValues([]interface{}{titleOrRegExp}, false, true, nil)
+ if err != nil {
+ return err
+ }
+ return pa.expect(
+ "to.have.title",
+ frameExpectOptions{ExpectedText: expectedValues, Timeout: timeout},
+ titleOrRegExp,
+ "Page title expected to be",
+ )
+}
+
+func (pa *pageAssertionsImpl) ToHaveURL(urlOrRegExp interface{}, options ...PageAssertionsToHaveURLOptions) error {
+ var timeout *float64
+ var ignoreCase *bool
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ ignoreCase = options[0].IgnoreCase
+ }
+
+ baseURL := pa.actualPage.Context().(*browserContextImpl).options.BaseURL
+ if urlPath, ok := urlOrRegExp.(string); ok && baseURL != nil {
+ u, _ := url.Parse(*baseURL)
+ u.Path = path.Join(u.Path, urlPath)
+ urlOrRegExp = u.String()
+ }
+
+ expectedValues, err := toExpectedTextValues([]interface{}{urlOrRegExp}, false, false, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return pa.expect(
+ "to.have.url",
+ frameExpectOptions{ExpectedText: expectedValues, Timeout: timeout},
+ urlOrRegExp,
+ "Page URL expected to be",
+ )
+}
+
+func (pa *pageAssertionsImpl) Not() PageAssertions {
+ return newPageAssertions(pa.actualPage, true, pa.defaultTimeout)
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/playwright.go b/vendor/github.com/playwright-community/playwright-go/playwright.go
new file mode 100644
index 0000000..805ac14
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/playwright.go
@@ -0,0 +1,64 @@
+// Package playwright is a library to automate Chromium, Firefox and WebKit with
+// a single API. Playwright is built to enable cross-browser web automation that
+// is ever-green, capable, reliable and fast.
+package playwright
+
+// DeviceDescriptor represents a single device
+type DeviceDescriptor struct {
+ UserAgent string `json:"userAgent"`
+ Viewport *Size `json:"viewport"`
+ Screen *Size `json:"screen"`
+ DeviceScaleFactor float64 `json:"deviceScaleFactor"`
+ IsMobile bool `json:"isMobile"`
+ HasTouch bool `json:"hasTouch"`
+ DefaultBrowserType string `json:"defaultBrowserType"`
+}
+
+// Playwright represents a Playwright instance
+type Playwright struct {
+ channelOwner
+ Selectors Selectors
+ Chromium BrowserType
+ Firefox BrowserType
+ WebKit BrowserType
+ Request APIRequest
+ Devices map[string]*DeviceDescriptor
+}
+
+// Stop stops the Playwright instance
+func (p *Playwright) Stop() error {
+ return p.connection.Stop()
+}
+
+func (p *Playwright) setSelectors(selectors Selectors) {
+ selectorsOwner := fromChannel(p.initializer["selectors"]).(*selectorsOwnerImpl)
+ p.Selectors.(*selectorsImpl).removeChannel(selectorsOwner)
+ p.Selectors = selectors
+ p.Selectors.(*selectorsImpl).addChannel(selectorsOwner)
+}
+
+func newPlaywright(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *Playwright {
+ pw := &Playwright{
+ Selectors: newSelectorsImpl(),
+ Chromium: fromChannel(initializer["chromium"]).(*browserTypeImpl),
+ Firefox: fromChannel(initializer["firefox"]).(*browserTypeImpl),
+ WebKit: fromChannel(initializer["webkit"]).(*browserTypeImpl),
+ Devices: make(map[string]*DeviceDescriptor),
+ }
+ pw.createChannelOwner(pw, parent, objectType, guid, initializer)
+ pw.Request = newApiRequestImpl(pw)
+ pw.Chromium.(*browserTypeImpl).playwright = pw
+ pw.Firefox.(*browserTypeImpl).playwright = pw
+ pw.WebKit.(*browserTypeImpl).playwright = pw
+ selectorsOwner := fromChannel(initializer["selectors"]).(*selectorsOwnerImpl)
+ pw.Selectors.(*selectorsImpl).addChannel(selectorsOwner)
+ pw.connection.afterClose = func() {
+ pw.Selectors.(*selectorsImpl).removeChannel(selectorsOwner)
+ }
+ if pw.connection.localUtils != nil {
+ pw.Devices = pw.connection.localUtils.Devices
+ }
+ return pw
+}
+
+//go:generate bash scripts/generate-api.sh
diff --git a/vendor/github.com/playwright-community/playwright-go/request.go b/vendor/github.com/playwright-community/playwright-go/request.go
new file mode 100644
index 0000000..43a3161
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/request.go
@@ -0,0 +1,274 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+)
+
+type serializedFallbackOverrides struct {
+ URL *string
+ Method *string
+ Headers map[string]string
+ PostDataBuffer []byte
+}
+
+type requestImpl struct {
+ channelOwner
+ timing *RequestTiming
+ provisionalHeaders *rawHeaders
+ allHeaders *rawHeaders
+ redirectedFrom Request
+ redirectedTo Request
+ failureText string
+ fallbackOverrides *serializedFallbackOverrides
+}
+
+func (r *requestImpl) URL() string {
+ if r.fallbackOverrides.URL != nil {
+ return *r.fallbackOverrides.URL
+ }
+ return r.initializer["url"].(string)
+}
+
+func (r *requestImpl) ResourceType() string {
+ return r.initializer["resourceType"].(string)
+}
+
+func (r *requestImpl) Method() string {
+ if r.fallbackOverrides.Method != nil {
+ return *r.fallbackOverrides.Method
+ }
+ return r.initializer["method"].(string)
+}
+
+func (r *requestImpl) PostData() (string, error) {
+ body, err := r.PostDataBuffer()
+ if err != nil {
+ return "", err
+ }
+ return string(body), err
+}
+
+func (r *requestImpl) PostDataJSON(v interface{}) error {
+ body, err := r.PostDataBuffer()
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(body, v)
+}
+
+func (r *requestImpl) PostDataBuffer() ([]byte, error) {
+ if r.fallbackOverrides.PostDataBuffer != nil {
+ return r.fallbackOverrides.PostDataBuffer, nil
+ }
+ if _, ok := r.initializer["postData"]; !ok {
+ return nil, nil
+ }
+ return base64.StdEncoding.DecodeString(r.initializer["postData"].(string))
+}
+
+func (r *requestImpl) Headers() map[string]string {
+ if r.fallbackOverrides.Headers != nil {
+ return newRawHeaders(serializeMapToNameAndValue(r.fallbackOverrides.Headers)).Headers()
+ }
+ return r.provisionalHeaders.Headers()
+}
+
+func (r *requestImpl) Response() (Response, error) {
+ channel, err := r.channel.Send("response")
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ // no response
+ return nil, nil
+ }
+ return channelOwner.(*responseImpl), nil
+}
+
+func (r *requestImpl) Frame() Frame {
+ channel, ok := r.initializer["frame"]
+ if !ok {
+ // Service Worker requests do not have an associated frame.
+ return nil
+ }
+ frame := fromChannel(channel).(*frameImpl)
+ if frame.page == nil {
+ // Frame for this navigation request is not available, because the request
+ // was issued before the frame is created. You can check whether the request
+ // is a navigation request by calling IsNavigationRequest() method.
+ return nil
+ }
+ return frame
+}
+
+func (r *requestImpl) IsNavigationRequest() bool {
+ return r.initializer["isNavigationRequest"].(bool)
+}
+
+func (r *requestImpl) RedirectedFrom() Request {
+ return r.redirectedFrom
+}
+
+func (r *requestImpl) RedirectedTo() Request {
+ return r.redirectedTo
+}
+
+func (r *requestImpl) Failure() error {
+ if r.failureText == "" {
+ return nil
+ }
+ return fmt.Errorf("%v", r.failureText)
+}
+
+func (r *requestImpl) Timing() *RequestTiming {
+ return r.timing
+}
+
+func (r *requestImpl) AllHeaders() (map[string]string, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return nil, err
+ }
+ return headers.Headers(), nil
+}
+
+func (r *requestImpl) HeadersArray() ([]NameValue, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return nil, err
+ }
+ return headers.HeadersArray(), nil
+}
+
+func (r *requestImpl) HeaderValue(name string) (string, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return "", err
+ }
+ return headers.Get(name), err
+}
+
+func (r *requestImpl) HeaderValues(name string) ([]string, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return []string{}, err
+ }
+ return headers.GetAll(name), err
+}
+
+func (r *requestImpl) ActualHeaders() (*rawHeaders, error) {
+ if r.fallbackOverrides.Headers != nil {
+ return newRawHeaders(serializeMapToNameAndValue(r.fallbackOverrides.Headers)), nil
+ }
+ if r.allHeaders == nil {
+ response, err := r.Response()
+ if err != nil {
+ return nil, err
+ }
+ if response == nil {
+ return r.provisionalHeaders, nil
+ }
+ headers, err := r.channel.Send("rawRequestHeaders")
+ if err != nil {
+ return nil, err
+ }
+ r.allHeaders = newRawHeaders(headers)
+ }
+ return r.allHeaders, nil
+}
+
+func (r *requestImpl) ServiceWorker() Worker {
+ channel, ok := r.initializer["serviceWorker"]
+ if !ok {
+ return nil
+ }
+ return fromChannel(channel).(*workerImpl)
+}
+
+func (r *requestImpl) Sizes() (*RequestSizesResult, error) {
+ response, err := r.Response()
+ if err != nil {
+ return nil, err
+ }
+ sizes, err := response.(*responseImpl).channel.Send("sizes")
+ if err != nil {
+ return nil, err
+ }
+ result := &RequestSizesResult{}
+ remapMapToStruct(sizes, result)
+ return result, nil
+}
+
+func (r *requestImpl) applyFallbackOverrides(options RouteFallbackOptions) {
+ if options.URL != nil {
+ r.fallbackOverrides.URL = options.URL
+ }
+ if options.Method != nil {
+ r.fallbackOverrides.Method = options.Method
+ }
+ r.fallbackOverrides.Headers = options.Headers
+ if options.PostData != nil {
+ switch v := options.PostData.(type) {
+ case string:
+ r.fallbackOverrides.PostDataBuffer = []byte(v)
+ case []byte:
+ r.fallbackOverrides.PostDataBuffer = v
+ }
+ }
+}
+
+func (r *requestImpl) targetClosed() <-chan error {
+ page := r.safePage()
+ if page == nil {
+ return make(<-chan error, 1)
+ }
+ return page.closedOrCrashed
+}
+
+func (r *requestImpl) setResponseEndTiming(t float64) {
+ r.timing.ResponseEnd = t
+ if r.timing.ResponseStart == -1 {
+ r.timing.ResponseStart = t
+ }
+}
+
+func (r *requestImpl) safePage() *pageImpl {
+ channel := fromNullableChannel(r.initializer["frame"])
+ if channel == nil {
+ return nil
+ }
+ frame, ok := channel.(*frameImpl)
+ if !ok {
+ return nil
+ }
+ return frame.page
+}
+
+func newRequest(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *requestImpl {
+ req := &requestImpl{}
+ req.createChannelOwner(req, parent, objectType, guid, initializer)
+ redirectedFrom := fromNullableChannel(initializer["redirectedFrom"])
+ if redirectedFrom != nil {
+ req.redirectedFrom = redirectedFrom.(*requestImpl)
+ }
+ if req.redirectedFrom != nil {
+ req.redirectedFrom.(*requestImpl).redirectedTo = req
+ }
+ req.timing = &RequestTiming{
+ StartTime: 0,
+ DomainLookupStart: -1,
+ DomainLookupEnd: -1,
+ ConnectStart: -1,
+ SecureConnectionStart: -1,
+ ConnectEnd: -1,
+ RequestStart: -1,
+ ResponseStart: -1,
+ ResponseEnd: -1,
+ }
+ req.provisionalHeaders = newRawHeaders(req.initializer["headers"])
+ req.fallbackOverrides = &serializedFallbackOverrides{}
+ return req
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/response.go b/vendor/github.com/playwright-community/playwright-go/response.go
new file mode 100644
index 0000000..8f26d6d
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/response.go
@@ -0,0 +1,162 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "encoding/json"
+)
+
+type responseImpl struct {
+ channelOwner
+ request *requestImpl
+ provisionalHeaders *rawHeaders
+ rawHeaders *rawHeaders
+ finished chan error
+}
+
+func (r *responseImpl) FromServiceWorker() bool {
+ return r.initializer["fromServiceWorker"].(bool)
+}
+
+func (r *responseImpl) URL() string {
+ return r.initializer["url"].(string)
+}
+
+func (r *responseImpl) Ok() bool {
+ return r.Status() == 0 || (r.Status() >= 200 && r.Status() <= 299)
+}
+
+func (r *responseImpl) Status() int {
+ return int(r.initializer["status"].(float64))
+}
+
+func (r *responseImpl) StatusText() string {
+ return r.initializer["statusText"].(string)
+}
+
+func (r *responseImpl) Headers() map[string]string {
+ return r.provisionalHeaders.Headers()
+}
+
+func (r *responseImpl) Finished() error {
+ select {
+ case err := <-r.request.targetClosed():
+ return err
+ case err := <-r.finished:
+ return err
+ }
+}
+
+func (r *responseImpl) Body() ([]byte, error) {
+ b64Body, err := r.channel.Send("body")
+ if err != nil {
+ return nil, err
+ }
+ return base64.StdEncoding.DecodeString(b64Body.(string))
+}
+
+func (r *responseImpl) Text() (string, error) {
+ body, err := r.Body()
+ if err != nil {
+ return "", err
+ }
+ return string(body), nil
+}
+
+func (r *responseImpl) JSON(v interface{}) error {
+ body, err := r.Body()
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(body, v)
+}
+
+func (r *responseImpl) Request() Request {
+ return r.request
+}
+
+func (r *responseImpl) Frame() Frame {
+ return r.request.Frame()
+}
+
+func (r *responseImpl) AllHeaders() (map[string]string, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return nil, err
+ }
+ return headers.Headers(), nil
+}
+
+func (r *responseImpl) HeadersArray() ([]NameValue, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return nil, err
+ }
+ return headers.HeadersArray(), nil
+}
+
+func (r *responseImpl) HeaderValue(name string) (string, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return "", err
+ }
+ return headers.Get(name), err
+}
+
+func (r *responseImpl) HeaderValues(name string) ([]string, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return []string{}, err
+ }
+ return headers.GetAll(name), err
+}
+
+func (r *responseImpl) ActualHeaders() (*rawHeaders, error) {
+ if r.rawHeaders == nil {
+ headers, err := r.channel.Send("rawResponseHeaders")
+ if err != nil {
+ return nil, err
+ }
+ r.rawHeaders = newRawHeaders(headers)
+ }
+ return r.rawHeaders, nil
+}
+
+func (r *responseImpl) SecurityDetails() (*ResponseSecurityDetailsResult, error) {
+ details, err := r.channel.Send("securityDetails")
+ if err != nil {
+ return nil, err
+ }
+ result := &ResponseSecurityDetailsResult{}
+ remapMapToStruct(details.(map[string]interface{}), result)
+ return result, nil
+}
+
+func (r *responseImpl) ServerAddr() (*ResponseServerAddrResult, error) {
+ addr, err := r.channel.Send("serverAddr")
+ if err != nil {
+ return nil, err
+ }
+ result := &ResponseServerAddrResult{}
+ remapMapToStruct(addr, result)
+ return result, nil
+}
+
+func newResponse(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *responseImpl {
+ resp := &responseImpl{}
+ resp.createChannelOwner(resp, parent, objectType, guid, initializer)
+ timing := resp.initializer["timing"].(map[string]interface{})
+ resp.request = fromChannel(resp.initializer["request"]).(*requestImpl)
+ resp.request.timing = &RequestTiming{
+ StartTime: timing["startTime"].(float64),
+ DomainLookupStart: timing["domainLookupStart"].(float64),
+ DomainLookupEnd: timing["domainLookupEnd"].(float64),
+ ConnectStart: timing["connectStart"].(float64),
+ SecureConnectionStart: timing["secureConnectionStart"].(float64),
+ ConnectEnd: timing["connectEnd"].(float64),
+ RequestStart: timing["requestStart"].(float64),
+ ResponseStart: timing["responseStart"].(float64),
+ }
+ resp.provisionalHeaders = newRawHeaders(resp.initializer["headers"])
+ resp.finished = make(chan error, 1)
+ return resp
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/route.go b/vendor/github.com/playwright-community/playwright-go/route.go
new file mode 100644
index 0000000..c9e6ee9
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/route.go
@@ -0,0 +1,270 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "errors"
+ "net/http"
+ "os"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+type routeImpl struct {
+ channelOwner
+ handling *chan bool
+ context *browserContextImpl
+ didThrow bool
+}
+
+func (r *routeImpl) startHandling() chan bool {
+ r.Lock()
+ defer r.Unlock()
+ handling := make(chan bool, 1)
+ r.handling = &handling
+ return handling
+}
+
+func (r *routeImpl) reportHandled(done bool) {
+ r.Lock()
+ defer r.Unlock()
+ if r.handling != nil {
+ handling := *r.handling
+ r.handling = nil
+ handling <- done
+ }
+}
+
+func (r *routeImpl) checkNotHandled() error {
+ r.RLock()
+ defer r.RUnlock()
+ if r.handling == nil {
+ return errors.New("Route is already handled!")
+ }
+ return nil
+}
+
+func (r *routeImpl) Request() Request {
+ return fromChannel(r.initializer["request"]).(*requestImpl)
+}
+
+func unpackOptionalArgument(input interface{}) interface{} {
+ inputValue := reflect.ValueOf(input)
+ if inputValue.Kind() != reflect.Slice {
+ panic("Needs to be a slice")
+ }
+ if inputValue.Len() == 0 {
+ return nil
+ }
+ return inputValue.Index(0).Interface()
+}
+
+func (r *routeImpl) Abort(errorCode ...string) error {
+ return r.handleRoute(func() error {
+ return r.raceWithPageClose(func() error {
+ _, err := r.channel.Send("abort", map[string]interface{}{
+ "errorCode": unpackOptionalArgument(errorCode),
+ })
+ return err
+ })
+ })
+}
+
+func (r *routeImpl) raceWithPageClose(f func() error) error {
+ errChan := make(chan error, 1)
+ go func() {
+ errChan <- f()
+ }()
+
+ select {
+ case <-r.Request().(*requestImpl).targetClosed():
+ // upstream does not throw the err
+ return nil
+ case err := <-errChan:
+ return err
+ }
+}
+
+func (r *routeImpl) Fulfill(options ...RouteFulfillOptions) error {
+ return r.handleRoute(func() error {
+ return r.innerFulfill(options...)
+ })
+}
+
+func (r *routeImpl) handleRoute(cb func() error) error {
+ err := r.checkNotHandled()
+ if err != nil {
+ return err
+ }
+ if err := cb(); err != nil {
+ r.didThrow = true
+ return err
+ }
+ r.reportHandled(true)
+ return nil
+}
+
+func (r *routeImpl) innerFulfill(options ...RouteFulfillOptions) error {
+ err := r.checkNotHandled()
+ if err != nil {
+ return err
+ }
+ option := RouteFulfillOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ overrides := map[string]interface{}{
+ "status": 200,
+ }
+ headers := make(map[string]string)
+
+ if option.Response != nil {
+ overrides["status"] = option.Response.Status()
+ headers = option.Response.Headers()
+ response, ok := option.Response.(*apiResponseImpl)
+ if option.Body == nil && option.Path == nil && ok && response.request.connection == r.connection {
+ overrides["fetchResponseUid"] = response.fetchUid()
+ } else {
+ option.Body, _ = option.Response.Body()
+ }
+ option.Response = nil
+ }
+ if option.Status != nil {
+ overrides["status"] = *option.Status
+ option.Status = nil
+ }
+
+ length := 0
+ isBase64 := false
+ var fileContentType string
+ if _, ok := option.Body.(string); ok {
+ isBase64 = false
+ } else if body, ok := option.Body.([]byte); ok {
+ option.Body = base64.StdEncoding.EncodeToString(body)
+ length = len(body)
+ isBase64 = true
+ } else if option.Path != nil {
+ content, err := os.ReadFile(*option.Path)
+ if err != nil {
+ return err
+ }
+ fileContentType = http.DetectContentType(content)
+ option.Body = base64.StdEncoding.EncodeToString(content)
+ isBase64 = true
+ length = len(content)
+ }
+
+ if option.Headers != nil {
+ headers = make(map[string]string)
+ for key, val := range option.Headers {
+ headers[strings.ToLower(key)] = val
+ }
+ option.Headers = nil
+ }
+ if option.ContentType != nil {
+ headers["content-type"] = *option.ContentType
+ option.ContentType = nil
+ } else if option.Path != nil {
+ headers["content-type"] = fileContentType
+ }
+ if _, ok := headers["content-length"]; !ok && length > 0 {
+ headers["content-length"] = strconv.Itoa(length)
+ }
+ overrides["headers"] = serializeMapToNameAndValue(headers)
+ overrides["isBase64"] = isBase64
+
+ option.Path = nil
+ err = r.raceWithPageClose(func() error {
+ _, err := r.channel.Send("fulfill", option, overrides)
+ return err
+ })
+ return err
+}
+
+func (r *routeImpl) Fallback(options ...RouteFallbackOptions) error {
+ err := r.checkNotHandled()
+ if err != nil {
+ return err
+ }
+ opt := RouteFallbackOptions{}
+ if len(options) == 1 {
+ opt = options[0]
+ }
+ r.Request().(*requestImpl).applyFallbackOverrides(opt)
+ r.reportHandled(false)
+ return nil
+}
+
+func (r *routeImpl) Fetch(options ...RouteFetchOptions) (APIResponse, error) {
+ opt := &APIRequestContextFetchOptions{}
+ url := ""
+ if len(options) == 1 {
+ err := assignStructFields(opt, options[0], true)
+ if err != nil {
+ return nil, err
+ }
+ opt.Data = options[0].PostData
+ if options[0].URL != nil {
+ url = *options[0].URL
+ }
+ }
+ ret, err := r.connection.WrapAPICall(func() (interface{}, error) {
+ return r.context.request.innerFetch(url, r.Request(), *opt)
+ }, false)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(APIResponse), err
+}
+
+func (r *routeImpl) Continue(options ...RouteContinueOptions) error {
+ option := &RouteFallbackOptions{}
+ if len(options) == 1 {
+ err := assignStructFields(option, options[0], true)
+ if err != nil {
+ return err
+ }
+ }
+
+ return r.handleRoute(func() error {
+ r.Request().(*requestImpl).applyFallbackOverrides(*option)
+ return r.internalContinue(false)
+ })
+}
+
+func (r *routeImpl) internalContinue(isFallback bool) error {
+ overrides := make(map[string]interface{})
+ overrides["url"] = r.Request().(*requestImpl).fallbackOverrides.URL
+ overrides["method"] = r.Request().(*requestImpl).fallbackOverrides.Method
+ headers := r.Request().(*requestImpl).fallbackOverrides.Headers
+ if headers != nil {
+ overrides["headers"] = serializeMapToNameAndValue(headers)
+ }
+ postDataBuf := r.Request().(*requestImpl).fallbackOverrides.PostDataBuffer
+ if postDataBuf != nil {
+ overrides["postData"] = base64.StdEncoding.EncodeToString(postDataBuf)
+ }
+ overrides["isFallback"] = isFallback
+ return r.raceWithPageClose(func() error {
+ _, err := r.channel.Send("continue", overrides)
+ return err
+ })
+}
+
+func (r *routeImpl) redirectedNavigationRequest(url string) error {
+ return r.handleRoute(func() error {
+ return r.raceWithPageClose(func() error {
+ _, err := r.channel.Send("redirectNavigationRequest", map[string]interface{}{
+ "url": url,
+ })
+ return err
+ })
+ })
+}
+
+func newRoute(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *routeImpl {
+ bt := &routeImpl{}
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ bt.markAsInternalType()
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/run.go b/vendor/github.com/playwright-community/playwright-go/run.go
new file mode 100644
index 0000000..79ad11e
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/run.go
@@ -0,0 +1,409 @@
+package playwright
+
+import (
+ "archive/zip"
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "log/slog"
+ "net/http"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+)
+
+const playwrightCliVersion = "1.52.0"
+
+var (
+ logger = slog.Default()
+ playwrightCDNMirrors = []string{
+ "https://playwright.azureedge.net",
+ "https://playwright-akamai.azureedge.net",
+ "https://playwright-verizon.azureedge.net",
+ }
+)
+
+// PlaywrightDriver wraps the Playwright CLI of upstream Playwright.
+//
+// It's required for playwright-go to work.
+type PlaywrightDriver struct {
+ Version string
+ options *RunOptions
+}
+
+func NewDriver(options ...*RunOptions) (*PlaywrightDriver, error) {
+ transformed, err := transformRunOptions(options...) // get default values
+ if err != nil {
+ return nil, err
+ }
+ return &PlaywrightDriver{
+ options: transformed,
+ Version: playwrightCliVersion,
+ }, nil
+}
+
+func getDefaultCacheDirectory() (string, error) {
+ userHomeDir, err := os.UserHomeDir()
+ if err != nil {
+ return "", fmt.Errorf("could not get user home directory: %w", err)
+ }
+ switch runtime.GOOS {
+ case "windows":
+ return filepath.Join(userHomeDir, "AppData", "Local"), nil
+ case "darwin":
+ return filepath.Join(userHomeDir, "Library", "Caches"), nil
+ case "linux":
+ return filepath.Join(userHomeDir, ".cache"), nil
+ }
+ return "", errors.New("could not determine cache directory")
+}
+
+func (d *PlaywrightDriver) isUpToDateDriver() (bool, error) {
+ if _, err := os.Stat(d.options.DriverDirectory); os.IsNotExist(err) {
+ if err := os.MkdirAll(d.options.DriverDirectory, 0o777); err != nil {
+ return false, fmt.Errorf("could not create driver directory: %w", err)
+ }
+ }
+ if _, err := os.Stat(getDriverCliJs(d.options.DriverDirectory)); os.IsNotExist(err) {
+ return false, nil
+ } else if err != nil {
+ return false, fmt.Errorf("could not check if driver is up2date: %w", err)
+ }
+ cmd := d.Command("--version")
+ output, err := cmd.Output()
+ if err != nil {
+ return false, fmt.Errorf("could not run driver: %w", err)
+ }
+ if bytes.Contains(output, []byte(d.Version)) {
+ return true, nil
+ }
+ // avoid triggering downloads and accidentally overwriting files
+ return false, fmt.Errorf("driver exists but version not %s in : %s", d.Version, d.options.DriverDirectory)
+}
+
+// Command returns an exec.Cmd for the driver.
+func (d *PlaywrightDriver) Command(arg ...string) *exec.Cmd {
+ cmd := exec.Command(getNodeExecutable(d.options.DriverDirectory), append([]string{getDriverCliJs(d.options.DriverDirectory)}, arg...)...)
+ cmd.SysProcAttr = defaultSysProcAttr
+ return cmd
+}
+
+// Install downloads the driver and the browsers depending on [RunOptions].
+func (d *PlaywrightDriver) Install() error {
+ if err := d.DownloadDriver(); err != nil {
+ return fmt.Errorf("could not install driver: %w", err)
+ }
+ if d.options.SkipInstallBrowsers {
+ return nil
+ }
+
+ d.log("Downloading browsers...")
+ if err := d.installBrowsers(); err != nil {
+ return fmt.Errorf("could not install browsers: %w", err)
+ }
+ d.log("Downloaded browsers successfully")
+
+ return nil
+}
+
+// Uninstall removes the driver and the browsers.
+func (d *PlaywrightDriver) Uninstall() error {
+ d.log("Removing browsers...")
+ if err := d.uninstallBrowsers(); err != nil {
+ return fmt.Errorf("could not uninstall browsers: %w", err)
+ }
+
+ d.log("Removing driver...")
+ if err := os.RemoveAll(d.options.DriverDirectory); err != nil {
+ return fmt.Errorf("could not remove driver directory: %w", err)
+ }
+
+ d.log("Uninstall driver successfully")
+ return nil
+}
+
+// DownloadDriver downloads the driver only
+func (d *PlaywrightDriver) DownloadDriver() error {
+ up2Date, err := d.isUpToDateDriver()
+ if err != nil {
+ return err
+ }
+ if up2Date {
+ return nil
+ }
+
+ d.log("Downloading driver", "path", d.options.DriverDirectory)
+
+ body, err := downloadDriver(d.getDriverURLs())
+ if err != nil {
+ return err
+ }
+ zipReader, err := zip.NewReader(bytes.NewReader(body), int64(len(body)))
+ if err != nil {
+ return fmt.Errorf("could not read zip content: %w", err)
+ }
+
+ for _, zipFile := range zipReader.File {
+ zipFileDiskPath := filepath.Join(d.options.DriverDirectory, zipFile.Name)
+ if zipFile.FileInfo().IsDir() {
+ if err := os.MkdirAll(zipFileDiskPath, os.ModePerm); err != nil {
+ return fmt.Errorf("could not create directory: %w", err)
+ }
+ continue
+ }
+
+ outFile, err := os.Create(zipFileDiskPath)
+ if err != nil {
+ return fmt.Errorf("could not create driver: %w", err)
+ }
+ file, err := zipFile.Open()
+ if err != nil {
+ return fmt.Errorf("could not open zip file: %w", err)
+ }
+ if _, err = io.Copy(outFile, file); err != nil {
+ return fmt.Errorf("could not copy response body to file: %w", err)
+ }
+ if err := outFile.Close(); err != nil {
+ return fmt.Errorf("could not close file (driver): %w", err)
+ }
+ if err := file.Close(); err != nil {
+ return fmt.Errorf("could not close file (zip file): %w", err)
+ }
+ if zipFile.Mode().Perm()&0o100 != 0 && runtime.GOOS != "windows" {
+ if err := makeFileExecutable(zipFileDiskPath); err != nil {
+ return fmt.Errorf("could not make executable: %w", err)
+ }
+ }
+ }
+
+ d.log("Downloaded driver successfully")
+
+ return nil
+}
+
+func (d *PlaywrightDriver) log(msg string, args ...any) {
+ if d.options.Verbose {
+ logger.Info(msg, args...)
+ }
+}
+
+func (d *PlaywrightDriver) run() (*connection, error) {
+ transport, err := newPipeTransport(d, d.options.Stderr)
+ if err != nil {
+ return nil, err
+ }
+ connection := newConnection(transport)
+ return connection, nil
+}
+
+func (d *PlaywrightDriver) installBrowsers() error {
+ additionalArgs := []string{"install"}
+ if d.options.Browsers != nil {
+ additionalArgs = append(additionalArgs, d.options.Browsers...)
+ }
+
+ if d.options.OnlyInstallShell {
+ additionalArgs = append(additionalArgs, "--only-shell")
+ }
+
+ if d.options.DryRun {
+ additionalArgs = append(additionalArgs, "--dry-run")
+ }
+
+ cmd := d.Command(additionalArgs...)
+ cmd.Stdout = d.options.Stdout
+ cmd.Stderr = d.options.Stderr
+ return cmd.Run()
+}
+
+func (d *PlaywrightDriver) uninstallBrowsers() error {
+ cmd := d.Command("uninstall")
+ cmd.Stdout = d.options.Stdout
+ cmd.Stderr = d.options.Stderr
+ return cmd.Run()
+}
+
+// RunOptions are custom options to run the driver
+type RunOptions struct {
+ // DriverDirectory points to the playwright driver directory.
+ // It should have two subdirectories: node and package.
+ // You can also specify it using the environment variable PLAYWRIGHT_DRIVER_PATH.
+ //
+ // Default is user cache directory + "/ms-playwright-go/x.xx.xx":
+ // - Windows: %USERPROFILE%\AppData\Local
+ // - macOS: ~/Library/Caches
+ // - Linux: ~/.cache
+ DriverDirectory string
+ // OnlyInstallShell only downloads the headless shell. (For chromium browsers only)
+ OnlyInstallShell bool
+ SkipInstallBrowsers bool
+ // if not set and SkipInstallBrowsers is false, will download all browsers (chromium, firefox, webkit)
+ Browsers []string
+ Verbose bool // default true
+ Stdout io.Writer
+ Stderr io.Writer
+ Logger *slog.Logger
+ // DryRun does not install browser/dependencies. It will only print information.
+ DryRun bool
+}
+
+// Install does download the driver and the browsers.
+//
+// Use this before playwright.Run() or use playwright cli to install the driver and browsers
+func Install(options ...*RunOptions) error {
+ driver, err := NewDriver(options...)
+ if err != nil {
+ return fmt.Errorf("could not get driver instance: %w", err)
+ }
+ if err := driver.Install(); err != nil {
+ return fmt.Errorf("could not install driver: %w", err)
+ }
+ return nil
+}
+
+// Run starts a Playwright instance.
+//
+// Requires the driver and the browsers to be installed before.
+// Either use Install() or use playwright cli.
+func Run(options ...*RunOptions) (*Playwright, error) {
+ driver, err := NewDriver(options...)
+ if err != nil {
+ return nil, fmt.Errorf("could not get driver instance: %w", err)
+ }
+ up2date, err := driver.isUpToDateDriver()
+ if err != nil || !up2date {
+ return nil, fmt.Errorf("please install the driver (v%s) first: %w", playwrightCliVersion, err)
+ }
+ connection, err := driver.run()
+ if err != nil {
+ return nil, err
+ }
+ playwright, err := connection.Start()
+ return playwright, err
+}
+
+func transformRunOptions(options ...*RunOptions) (*RunOptions, error) {
+ option := &RunOptions{
+ Verbose: true,
+ }
+ if len(options) == 1 {
+ option = options[0]
+ }
+ if option.DriverDirectory == "" { // if user did not set it, try to get it from env
+ option.DriverDirectory = os.Getenv("PLAYWRIGHT_DRIVER_PATH")
+ }
+ if option.DriverDirectory == "" {
+ cacheDirectory, err := getDefaultCacheDirectory()
+ if err != nil {
+ return nil, fmt.Errorf("could not get default cache directory: %w", err)
+ }
+ option.DriverDirectory = filepath.Join(cacheDirectory, "ms-playwright-go", playwrightCliVersion)
+ }
+ if option.Stdout == nil {
+ option.Stdout = os.Stdout
+ }
+ if option.Stderr == nil {
+ option.Stderr = os.Stderr
+ } else if option.Logger == nil {
+ log.SetOutput(option.Stderr)
+ }
+ if option.Logger != nil {
+ logger = option.Logger
+ }
+ return option, nil
+}
+
+func getNodeExecutable(driverDirectory string) string {
+ envPath := os.Getenv("PLAYWRIGHT_NODEJS_PATH")
+ if envPath != "" {
+ return envPath
+ }
+
+ node := "node"
+ if runtime.GOOS == "windows" {
+ node = "node.exe"
+ }
+ return filepath.Join(driverDirectory, node)
+}
+
+func getDriverCliJs(driverDirectory string) string {
+ return filepath.Join(driverDirectory, "package", "cli.js")
+}
+
+func (d *PlaywrightDriver) getDriverURLs() []string {
+ platform := ""
+ switch runtime.GOOS {
+ case "windows":
+ platform = "win32_x64"
+ case "darwin":
+ if runtime.GOARCH == "arm64" {
+ platform = "mac-arm64"
+ } else {
+ platform = "mac"
+ }
+ case "linux":
+ if runtime.GOARCH == "arm64" {
+ platform = "linux-arm64"
+ } else {
+ platform = "linux"
+ }
+ }
+
+ baseURLs := []string{}
+ pattern := "%s/builds/driver/playwright-%s-%s.zip"
+ if !d.isReleaseVersion() {
+ pattern = "%s/builds/driver/next/playwright-%s-%s.zip"
+ }
+
+ if hostEnv := os.Getenv("PLAYWRIGHT_DOWNLOAD_HOST"); hostEnv != "" {
+ baseURLs = append(baseURLs, fmt.Sprintf(pattern, hostEnv, d.Version, platform))
+ } else {
+ for _, mirror := range playwrightCDNMirrors {
+ baseURLs = append(baseURLs, fmt.Sprintf(pattern, mirror, d.Version, platform))
+ }
+ }
+ return baseURLs
+}
+
+// isReleaseVersion checks if the version is not a beta or alpha release
+// this helps to determine the url from where to download the driver
+func (d *PlaywrightDriver) isReleaseVersion() bool {
+ return !strings.Contains(d.Version, "beta") && !strings.Contains(d.Version, "alpha") && !strings.Contains(d.Version, "next")
+}
+
+func makeFileExecutable(path string) error {
+ stats, err := os.Stat(path)
+ if err != nil {
+ return fmt.Errorf("could not stat driver: %w", err)
+ }
+ if err := os.Chmod(path, stats.Mode()|0x40); err != nil {
+ return fmt.Errorf("could not set permissions: %w", err)
+ }
+ return nil
+}
+
+func downloadDriver(driverURLs []string) (body []byte, e error) {
+ for _, driverURL := range driverURLs {
+ resp, err := http.Get(driverURL)
+ if err != nil {
+ e = errors.Join(e, fmt.Errorf("could not download driver from %s: %w", driverURL, err))
+ continue
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ e = errors.Join(e, fmt.Errorf("error: got non 200 status code: %d (%s) from %s", resp.StatusCode, resp.Status, driverURL))
+ continue
+ }
+ body, err = io.ReadAll(resp.Body)
+ if err != nil {
+ e = errors.Join(e, fmt.Errorf("could not read response body: %w", err))
+ continue
+ }
+ return body, nil
+ }
+ return nil, e
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/run_unix.go b/vendor/github.com/playwright-community/playwright-go/run_unix.go
new file mode 100644
index 0000000..8ff102b
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/run_unix.go
@@ -0,0 +1,10 @@
+//go:build !windows
+
+package playwright
+
+import "syscall"
+
+var defaultSysProcAttr = &syscall.SysProcAttr{}
+
+// for WritableStream.Copy
+const defaultCopyBufSize = 1024 * 1024
diff --git a/vendor/github.com/playwright-community/playwright-go/run_win.go b/vendor/github.com/playwright-community/playwright-go/run_win.go
new file mode 100644
index 0000000..fe7b50d
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/run_win.go
@@ -0,0 +1,10 @@
+//go:build windows
+
+package playwright
+
+import "syscall"
+
+var defaultSysProcAttr = &syscall.SysProcAttr{HideWindow: true}
+
+// for WritableStream.Copy
+const defaultCopyBufSize = 64 * 1024
diff --git a/vendor/github.com/playwright-community/playwright-go/selectors.go b/vendor/github.com/playwright-community/playwright-go/selectors.go
new file mode 100644
index 0000000..1151647
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/selectors.go
@@ -0,0 +1,88 @@
+package playwright
+
+import (
+ "errors"
+ "os"
+ "sync"
+)
+
+type selectorsOwnerImpl struct {
+ channelOwner
+}
+
+func (s *selectorsOwnerImpl) setTestIdAttributeName(name string) {
+ s.channel.SendNoReply("setTestIdAttributeName", map[string]interface{}{
+ "testIdAttributeName": name,
+ })
+}
+
+func newSelectorsOwner(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *selectorsOwnerImpl {
+ obj := &selectorsOwnerImpl{}
+ obj.createChannelOwner(obj, parent, objectType, guid, initializer)
+ return obj
+}
+
+type selectorsImpl struct {
+ channels sync.Map
+ registrations []map[string]interface{}
+}
+
+func (s *selectorsImpl) Register(name string, script Script, options ...SelectorsRegisterOptions) error {
+ if script.Path == nil && script.Content == nil {
+ return errors.New("Either source or path should be specified")
+ }
+ source := ""
+ if script.Path != nil {
+ content, err := os.ReadFile(*script.Path)
+ if err != nil {
+ return err
+ }
+ source = string(content)
+ } else {
+ source = *script.Content
+ }
+ params := map[string]interface{}{
+ "name": name,
+ "source": source,
+ }
+ if len(options) == 1 && options[0].ContentScript != nil {
+ params["contentScript"] = *options[0].ContentScript
+ }
+ var err error
+ s.channels.Range(func(key, value any) bool {
+ _, err = value.(*selectorsOwnerImpl).channel.Send("register", params)
+ return err == nil
+ })
+ if err != nil {
+ return err
+ }
+ s.registrations = append(s.registrations, params)
+ return nil
+}
+
+func (s *selectorsImpl) SetTestIdAttribute(name string) {
+ setTestIdAttributeName(name)
+ s.channels.Range(func(key, value any) bool {
+ value.(*selectorsOwnerImpl).setTestIdAttributeName(name)
+ return true
+ })
+}
+
+func (s *selectorsImpl) addChannel(channel *selectorsOwnerImpl) {
+ s.channels.Store(channel.guid, channel)
+ for _, params := range s.registrations {
+ channel.channel.SendNoReply("register", params)
+ channel.setTestIdAttributeName(getTestIdAttributeName())
+ }
+}
+
+func (s *selectorsImpl) removeChannel(channel *selectorsOwnerImpl) {
+ s.channels.Delete(channel.guid)
+}
+
+func newSelectorsImpl() *selectorsImpl {
+ return &selectorsImpl{
+ channels: sync.Map{},
+ registrations: make([]map[string]interface{}, 0),
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/stream.go b/vendor/github.com/playwright-community/playwright-go/stream.go
new file mode 100644
index 0000000..e23942f
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/stream.go
@@ -0,0 +1,68 @@
+package playwright
+
+import (
+ "bufio"
+ "encoding/base64"
+ "os"
+ "path/filepath"
+)
+
+type streamImpl struct {
+ channelOwner
+}
+
+func (s *streamImpl) SaveAs(path string) error {
+ err := os.MkdirAll(filepath.Dir(path), 0o777)
+ if err != nil {
+ return err
+ }
+ file, err := os.Create(path)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+ writer := bufio.NewWriter(file)
+ for {
+ binary, err := s.channel.Send("read", map[string]interface{}{"size": 1024 * 1024})
+ if err != nil {
+ return err
+ }
+ bytes, err := base64.StdEncoding.DecodeString(binary.(string))
+ if err != nil {
+ return err
+ }
+ if len(bytes) == 0 {
+ break
+ }
+ _, err = writer.Write(bytes)
+ if err != nil {
+ return err
+ }
+ }
+ return writer.Flush()
+}
+
+func (s *streamImpl) ReadAll() ([]byte, error) {
+ var data []byte
+ for {
+ binary, err := s.channel.Send("read", map[string]interface{}{"size": 1024 * 1024})
+ if err != nil {
+ return nil, err
+ }
+ bytes, err := base64.StdEncoding.DecodeString(binary.(string))
+ if err != nil {
+ return nil, err
+ }
+ if len(bytes) == 0 {
+ break
+ }
+ data = append(data, bytes...)
+ }
+ return data, nil
+}
+
+func newStream(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *streamImpl {
+ stream := &streamImpl{}
+ stream.createChannelOwner(stream, parent, objectType, guid, initializer)
+ return stream
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/tracing.go b/vendor/github.com/playwright-community/playwright-go/tracing.go
new file mode 100644
index 0000000..decd872
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/tracing.go
@@ -0,0 +1,164 @@
+package playwright
+
+import "fmt"
+
+type tracingImpl struct {
+ channelOwner
+ includeSources bool
+ isTracing bool
+ stacksId string
+ tracesDir string
+}
+
+func (t *tracingImpl) Start(options ...TracingStartOptions) error {
+ chunkOption := TracingStartChunkOptions{}
+ if len(options) == 1 {
+ if options[0].Sources != nil {
+ t.includeSources = *options[0].Sources
+ }
+ chunkOption.Name = options[0].Name
+ chunkOption.Title = options[0].Title
+ }
+ innerStart := func() (interface{}, error) {
+ if _, err := t.channel.Send("tracingStart", options); err != nil {
+ return "", err
+ }
+ return t.channel.Send("tracingStartChunk", chunkOption)
+ }
+ name, err := innerStart()
+ if err != nil {
+ return err
+ }
+ return t.startCollectingStacks(name.(string))
+}
+
+func (t *tracingImpl) StartChunk(options ...TracingStartChunkOptions) error {
+ name, err := t.channel.Send("tracingStartChunk", options)
+ if err != nil {
+ return err
+ }
+ return t.startCollectingStacks(name.(string))
+}
+
+func (t *tracingImpl) StopChunk(path ...string) error {
+ filePath := ""
+ if len(path) == 1 {
+ filePath = path[0]
+ }
+ return t.doStopChunk(filePath)
+}
+
+func (t *tracingImpl) Stop(path ...string) error {
+ filePath := ""
+ if len(path) == 1 {
+ filePath = path[0]
+ }
+ if err := t.doStopChunk(filePath); err != nil {
+ return err
+ }
+ _, err := t.channel.Send("tracingStop")
+ return err
+}
+
+func (t *tracingImpl) doStopChunk(filePath string) (err error) {
+ if t.isTracing {
+ t.isTracing = false
+ t.connection.setInTracing(false)
+ }
+ if filePath == "" {
+ // Not interested in artifacts.
+ _, err = t.channel.Send("tracingStopChunk", map[string]interface{}{
+ "mode": "discard",
+ })
+ if t.stacksId != "" {
+ return t.connection.LocalUtils().TraceDiscarded(t.stacksId)
+ }
+ return err
+ }
+
+ isLocal := !t.connection.isRemote
+ if isLocal {
+ result, err := t.channel.SendReturnAsDict("tracingStopChunk", map[string]interface{}{
+ "mode": "entries",
+ })
+ if err != nil {
+ return err
+ }
+ entries, ok := result["entries"]
+ if !ok {
+ return fmt.Errorf("could not convert result to map: %v", result)
+ }
+ _, err = t.connection.LocalUtils().Zip(localUtilsZipOptions{
+ ZipFile: filePath,
+ Entries: entries.([]interface{}),
+ StacksId: t.stacksId,
+ Mode: "write",
+ IncludeSources: t.includeSources,
+ })
+ return err
+ }
+
+ result, err := t.channel.SendReturnAsDict("tracingStopChunk", map[string]interface{}{
+ "mode": "archive",
+ })
+ if err != nil {
+ return err
+ }
+ artifactChannel, ok := result["artifact"]
+ if !ok {
+ return fmt.Errorf("could not convert result to map: %v", result)
+ }
+ // Save trace to the final local file.
+ artifact := fromNullableChannel(artifactChannel).(*artifactImpl)
+ // The artifact may be missing if the browser closed while stopping tracing.
+ if artifact == nil {
+ if t.stacksId != "" {
+ return t.connection.LocalUtils().TraceDiscarded(t.stacksId)
+ }
+ return
+ }
+ if err := artifact.SaveAs(filePath); err != nil {
+ return err
+ }
+ if err := artifact.Delete(); err != nil {
+ return err
+ }
+ _, err = t.connection.LocalUtils().Zip(localUtilsZipOptions{
+ ZipFile: filePath,
+ Entries: []interface{}{},
+ StacksId: t.stacksId,
+ Mode: "append",
+ IncludeSources: t.includeSources,
+ })
+ return err
+}
+
+func (t *tracingImpl) startCollectingStacks(name string) (err error) {
+ if !t.isTracing {
+ t.isTracing = true
+ t.connection.setInTracing(true)
+ }
+ t.stacksId, err = t.connection.LocalUtils().TracingStarted(name, t.tracesDir)
+ return
+}
+
+func (t *tracingImpl) Group(name string, options ...TracingGroupOptions) error {
+ var option TracingGroupOptions
+ if len(options) == 1 {
+ option = options[0]
+ }
+ _, err := t.channel.Send("tracingGroup", option, map[string]interface{}{"name": name})
+ return err
+}
+
+func (t *tracingImpl) GroupEnd() error {
+ _, err := t.channel.Send("tracingGroupEnd")
+ return err
+}
+
+func newTracing(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *tracingImpl {
+ bt := &tracingImpl{}
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ bt.markAsInternalType()
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/transport.go b/vendor/github.com/playwright-community/playwright-go/transport.go
new file mode 100644
index 0000000..1be3988
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/transport.go
@@ -0,0 +1,141 @@
+package playwright
+
+import (
+ "bufio"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "os"
+
+ "github.com/go-jose/go-jose/v3/json"
+)
+
+type transport interface {
+ Send(msg map[string]interface{}) error
+ Poll() (*message, error)
+ Close() error
+}
+
+type pipeTransport struct {
+ writer io.WriteCloser
+ bufReader *bufio.Reader
+ closed chan struct{}
+ onClose func() error
+}
+
+func (t *pipeTransport) Poll() (*message, error) {
+ if t.isClosed() {
+ return nil, fmt.Errorf("transport closed")
+ }
+
+ var length uint32
+ err := binary.Read(t.bufReader, binary.LittleEndian, &length)
+ if err != nil {
+ return nil, fmt.Errorf("could not read protocol padding: %w", err)
+ }
+
+ data := make([]byte, length)
+ _, err = io.ReadFull(t.bufReader, data)
+ if err != nil {
+ return nil, fmt.Errorf("could not read protocol data: %w", err)
+ }
+
+ msg := &message{}
+ if err := json.Unmarshal(data, &msg); err != nil {
+ return nil, fmt.Errorf("could not decode json: %w", err)
+ }
+ if os.Getenv("DEBUGP") != "" {
+ fmt.Fprintf(os.Stdout, "\x1b[33mRECV>\x1b[0m\n%s\n", data)
+ }
+ return msg, nil
+}
+
+type message struct {
+ ID int `json:"id"`
+ GUID string `json:"guid"`
+ Method string `json:"method,omitempty"`
+ Params map[string]interface{} `json:"params,omitempty"`
+ Result map[string]interface{} `json:"result,omitempty"`
+ Error *struct {
+ Error Error `json:"error"`
+ } `json:"error,omitempty"`
+}
+
+func (t *pipeTransport) Send(msg map[string]interface{}) error {
+ if t.isClosed() {
+ return fmt.Errorf("transport closed")
+ }
+ msgBytes, err := json.Marshal(msg)
+ if err != nil {
+ return fmt.Errorf("pipeTransport: could not marshal json: %w", err)
+ }
+ if os.Getenv("DEBUGP") != "" {
+ fmt.Fprintf(os.Stdout, "\x1b[32mSEND>\x1b[0m\n%s\n", msgBytes)
+ }
+
+ lengthPadding := make([]byte, 4)
+ binary.LittleEndian.PutUint32(lengthPadding, uint32(len(msgBytes)))
+ if _, err = t.writer.Write(append(lengthPadding, msgBytes...)); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (t *pipeTransport) Close() error {
+ select {
+ case <-t.closed:
+ return nil
+ default:
+ return t.onClose()
+ }
+}
+
+func (t *pipeTransport) isClosed() bool {
+ select {
+ case <-t.closed:
+ return true
+ default:
+ return false
+ }
+}
+
+func newPipeTransport(driver *PlaywrightDriver, stderr io.Writer) (transport, error) {
+ t := &pipeTransport{
+ closed: make(chan struct{}, 1),
+ }
+
+ cmd := driver.Command("run-driver")
+ cmd.Stderr = stderr
+ stdin, err := cmd.StdinPipe()
+ if err != nil {
+ return nil, fmt.Errorf("could not create stdin pipe: %w", err)
+ }
+ stdout, err := cmd.StdoutPipe()
+ if err != nil {
+ return nil, fmt.Errorf("could not create stdout pipe: %w", err)
+ }
+ t.writer = stdin
+ t.bufReader = bufio.NewReader(stdout)
+
+ t.onClose = func() error {
+ select {
+ case <-t.closed:
+ default:
+ close(t.closed)
+ }
+ if err := t.writer.Close(); err != nil {
+ return err
+ }
+ // playwright-cli will exit when its stdin is closed
+ if err := cmd.Wait(); err != nil {
+ return err
+ }
+ return nil
+ }
+
+ if err := cmd.Start(); err != nil {
+ return nil, fmt.Errorf("could not start driver: %w", err)
+ }
+
+ return t, nil
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/type_helpers.go b/vendor/github.com/playwright-community/playwright-go/type_helpers.go
new file mode 100644
index 0000000..d821e7c
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/type_helpers.go
@@ -0,0 +1,72 @@
+package playwright
+
+// String is a helper routine that allocates a new string value
+// to store v and returns a pointer to it.
+func String(v string) *string {
+ return &v
+}
+
+// Bool is a helper routine that allocates a new bool value
+// to store v and returns a pointer to it.
+func Bool(v bool) *bool {
+ return &v
+}
+
+// Int is a helper routine that allocates a new int32 value
+// to store v and returns a pointer to it.
+func Int(v int) *int {
+ return &v
+}
+
+// Float is a helper routine that allocates a new float64 value
+// to store v and returns a pointer to it.
+func Float(v float64) *float64 {
+ return &v
+}
+
+// Null will be used in certain scenarios where a strict nil pointer
+// check is not possible
+func Null() interface{} {
+ return "PW_NULL"
+}
+
+// StringSlice is a helper routine that allocates a new StringSlice value
+// to store v and returns a pointer to it.
+func StringSlice(v ...string) *[]string {
+ var o []string
+ o = append(o, v...)
+ return &o
+}
+
+// IntSlice is a helper routine that allocates a new IntSlice value
+// to store v and returns a pointer to it.
+func IntSlice(v ...int) *[]int {
+ var o []int
+ o = append(o, v...)
+ return &o
+}
+
+// ToOptionalStorageState converts StorageState to OptionalStorageState for use directly in [Browser.NewContext]
+func (s StorageState) ToOptionalStorageState() *OptionalStorageState {
+ cookies := make([]OptionalCookie, len(s.Cookies))
+ for i, c := range s.Cookies {
+ cookies[i] = c.ToOptionalCookie()
+ }
+ return &OptionalStorageState{
+ Origins: s.Origins,
+ Cookies: cookies,
+ }
+}
+
+func (c Cookie) ToOptionalCookie() OptionalCookie {
+ return OptionalCookie{
+ Name: c.Name,
+ Value: c.Value,
+ Domain: String(c.Domain),
+ Path: String(c.Path),
+ Expires: Float(c.Expires),
+ HttpOnly: Bool(c.HttpOnly),
+ Secure: Bool(c.Secure),
+ SameSite: c.SameSite,
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/video.go b/vendor/github.com/playwright-community/playwright-go/video.go
new file mode 100644
index 0000000..a57b61a
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/video.go
@@ -0,0 +1,97 @@
+package playwright
+
+import (
+ "errors"
+ "sync"
+)
+
+type videoImpl struct {
+ page *pageImpl
+ artifact *artifactImpl
+ artifactChan chan *artifactImpl
+ done chan struct{}
+ closeOnce sync.Once
+ isRemote bool
+}
+
+func (v *videoImpl) Path() (string, error) {
+ if v.isRemote {
+ return "", errors.New("Path is not available when connecting remotely. Use SaveAs() to save a local copy.")
+ }
+ v.getArtifact()
+ if v.artifact == nil {
+ return "", errors.New("Page did not produce any video frames")
+ }
+ return v.artifact.AbsolutePath(), nil
+}
+
+func (v *videoImpl) Delete() error {
+ v.getArtifact()
+ if v.artifact == nil {
+ return nil
+ }
+ return v.artifact.Delete()
+}
+
+func (v *videoImpl) SaveAs(path string) error {
+ if !v.page.IsClosed() {
+ return errors.New("Page is not yet closed. Close the page prior to calling SaveAs")
+ }
+ v.getArtifact()
+ if v.artifact == nil {
+ return errors.New("Page did not produce any video frames")
+ }
+ return v.artifact.SaveAs(path)
+}
+
+func (v *videoImpl) artifactReady(artifact *artifactImpl) {
+ v.artifactChan <- artifact
+}
+
+func (v *videoImpl) pageClosed(p Page) {
+ v.closeOnce.Do(func() {
+ close(v.done)
+ })
+}
+
+func (v *videoImpl) getArtifact() {
+ // prevent channel block if no video will be produced
+ if v.page.browserContext.options == nil {
+ v.pageClosed(v.page)
+ } else {
+ option := v.page.browserContext.options
+ if option == nil || option.RecordVideo == nil { // no recordVideo option
+ v.pageClosed(v.page)
+ }
+ }
+ select {
+ case artifact := <-v.artifactChan:
+ if artifact != nil {
+ v.artifact = artifact
+ }
+ case <-v.done: // page closed
+ select { // make sure get artifact if it's ready before page closed
+ case artifact := <-v.artifactChan:
+ if artifact != nil {
+ v.artifact = artifact
+ }
+ default:
+ }
+ }
+}
+
+func newVideo(page *pageImpl) *videoImpl {
+ video := &videoImpl{
+ page: page,
+ artifactChan: make(chan *artifactImpl, 1),
+ done: make(chan struct{}, 1),
+ isRemote: page.connection.isRemote,
+ }
+
+ if page.isClosed {
+ video.pageClosed(page)
+ } else {
+ page.OnClose(video.pageClosed)
+ }
+ return video
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/waiter.go b/vendor/github.com/playwright-community/playwright-go/waiter.go
new file mode 100644
index 0000000..fbcb39f
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/waiter.go
@@ -0,0 +1,181 @@
+package playwright
+
+import (
+ "context"
+ "fmt"
+ "reflect"
+ "sync"
+ "sync/atomic"
+ "time"
+)
+
+type (
+ waiter struct {
+ mu sync.Mutex
+ timeout float64
+ fulfilled atomic.Bool
+ listeners []eventListener
+ errChan chan error
+ waitFunc func() (interface{}, error)
+ }
+ eventListener struct {
+ emitter EventEmitter
+ event string
+ handler interface{}
+ }
+)
+
+// RejectOnEvent sets the Waiter to return an error when an event occurs (and the predicate returns true)
+func (w *waiter) RejectOnEvent(emitter EventEmitter, event string, err error, predicates ...interface{}) *waiter {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ if w.waitFunc != nil {
+ w.reject(fmt.Errorf("waiter: call RejectOnEvent before WaitForEvent"))
+ return w
+ }
+ handler := func(ev ...interface{}) {
+ if w.fulfilled.Load() {
+ return
+ }
+ if len(predicates) == 0 {
+ w.reject(err)
+ } else {
+ result := reflect.ValueOf(predicates[0]).Call([]reflect.Value{reflect.ValueOf(ev[0])})
+ if result[0].Bool() {
+ w.reject(err)
+ }
+ }
+ }
+ emitter.On(event, handler)
+ w.listeners = append(w.listeners, eventListener{
+ emitter: emitter,
+ event: event,
+ handler: handler,
+ })
+ return w
+}
+
+// WithTimeout sets timeout, in milliseconds, for the waiter. 0 means no timeout.
+func (w *waiter) WithTimeout(timeout float64) *waiter {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ if w.waitFunc != nil {
+ w.reject(fmt.Errorf("waiter: please set timeout before WaitForEvent"))
+ return w
+ }
+ w.timeout = timeout
+ return w
+}
+
+// WaitForEvent sets the Waiter to return when an event occurs (and the predicate returns true)
+func (w *waiter) WaitForEvent(emitter EventEmitter, event string, predicate interface{}) *waiter {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ if w.waitFunc != nil {
+ w.reject(fmt.Errorf("waiter: WaitForEvent can only be called once"))
+ return w
+ }
+ evChan := make(chan interface{}, 1)
+ handler := w.createHandler(evChan, predicate)
+ ctx, cancel := context.WithCancel(context.Background())
+ if w.timeout != 0 {
+ timeout := w.timeout
+ go func() {
+ select {
+ case <-time.After(time.Duration(timeout) * time.Millisecond):
+ err := fmt.Errorf("%w:Timeout %.2fms exceeded.", ErrTimeout, timeout)
+ w.reject(err)
+ return
+ case <-ctx.Done():
+ return
+ }
+ }()
+ }
+
+ emitter.On(event, handler)
+ w.listeners = append(w.listeners, eventListener{
+ emitter: emitter,
+ event: event,
+ handler: handler,
+ })
+
+ w.waitFunc = func() (interface{}, error) {
+ var (
+ err error
+ val interface{}
+ )
+ select {
+ case err = <-w.errChan:
+ break
+ case val = <-evChan:
+ break
+ }
+ cancel()
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ for _, l := range w.listeners {
+ l.emitter.RemoveListener(l.event, l.handler)
+ }
+ close(evChan)
+ if err != nil {
+ return nil, err
+ }
+ return val, nil
+ }
+ return w
+}
+
+// Wait waits for the waiter to return. It needs to call WaitForEvent once first.
+func (w *waiter) Wait() (interface{}, error) {
+ if w.waitFunc == nil {
+ return nil, fmt.Errorf("waiter: call WaitForEvent first")
+ }
+ return w.waitFunc()
+}
+
+// RunAndWait waits for the waiter to return after calls func.
+func (w *waiter) RunAndWait(cb func() error) (interface{}, error) {
+ if w.waitFunc == nil {
+ return nil, fmt.Errorf("waiter: call WaitForEvent first")
+ }
+ if cb != nil {
+ if err := cb(); err != nil {
+ w.errChan <- err
+ }
+ }
+ return w.waitFunc()
+}
+
+func (w *waiter) createHandler(evChan chan<- interface{}, predicate interface{}) func(...interface{}) {
+ return func(ev ...interface{}) {
+ if w.fulfilled.Load() {
+ return
+ }
+ if predicate == nil || reflect.ValueOf(predicate).IsNil() {
+ w.fulfilled.Store(true)
+ if len(ev) == 1 {
+ evChan <- ev[0]
+ } else {
+ evChan <- nil
+ }
+ } else {
+ result := reflect.ValueOf(predicate).Call([]reflect.Value{reflect.ValueOf(ev[0])})
+ if result[0].Bool() {
+ w.fulfilled.Store(true)
+ evChan <- ev[0]
+ }
+ }
+ }
+}
+
+func (w *waiter) reject(err error) {
+ w.fulfilled.Store(true)
+ w.errChan <- err
+}
+
+func newWaiter() *waiter {
+ w := &waiter{
+ errChan: make(chan error, 1),
+ }
+ return w
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/web_error.go b/vendor/github.com/playwright-community/playwright-go/web_error.go
new file mode 100644
index 0000000..b8dab79
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/web_error.go
@@ -0,0 +1,21 @@
+package playwright
+
+type webErrorImpl struct {
+ err error
+ page Page
+}
+
+func (e *webErrorImpl) Page() Page {
+ return e.page
+}
+
+func (e *webErrorImpl) Error() error {
+ return e.err
+}
+
+func newWebError(page Page, err error) WebError {
+ return &webErrorImpl{
+ err: err,
+ page: page,
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/websocket.go b/vendor/github.com/playwright-community/playwright-go/websocket.go
new file mode 100644
index 0000000..4d63ec3
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/websocket.go
@@ -0,0 +1,134 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "errors"
+)
+
+type webSocketImpl struct {
+ channelOwner
+ isClosed bool
+ page *pageImpl
+}
+
+func (ws *webSocketImpl) URL() string {
+ return ws.initializer["url"].(string)
+}
+
+func newWebsocket(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *webSocketImpl {
+ ws := &webSocketImpl{}
+ ws.createChannelOwner(ws, parent, objectType, guid, initializer)
+ ws.page = fromChannel(parent.channel).(*pageImpl)
+ ws.channel.On("close", func() {
+ ws.Lock()
+ ws.isClosed = true
+ ws.Unlock()
+ ws.Emit("close", ws)
+ })
+ ws.channel.On(
+ "frameSent",
+ func(params map[string]interface{}) {
+ ws.onFrameSent(params["opcode"].(float64), params["data"].(string))
+ },
+ )
+ ws.channel.On(
+ "frameReceived",
+ func(params map[string]interface{}) {
+ ws.onFrameReceived(params["opcode"].(float64), params["data"].(string))
+ },
+ )
+ ws.channel.On(
+ "socketError",
+ func(params map[string]interface{}) {
+ ws.Emit("socketerror", params["error"])
+ },
+ )
+ return ws
+}
+
+func (ws *webSocketImpl) onFrameSent(opcode float64, data string) {
+ if opcode == 2 {
+ payload, err := base64.StdEncoding.DecodeString(data)
+ if err != nil {
+ logger.Error("could not decode WebSocket.onFrameSent payload", "error", err)
+ return
+ }
+ ws.Emit("framesent", payload)
+ } else {
+ ws.Emit("framesent", []byte(data))
+ }
+}
+
+func (ws *webSocketImpl) onFrameReceived(opcode float64, data string) {
+ if opcode == 2 {
+ payload, err := base64.StdEncoding.DecodeString(data)
+ if err != nil {
+ logger.Error("could not decode WebSocket.onFrameReceived payload", "error", err)
+ return
+ }
+ ws.Emit("framereceived", payload)
+ } else {
+ ws.Emit("framereceived", []byte(data))
+ }
+}
+
+func (ws *webSocketImpl) ExpectEvent(event string, cb func() error, options ...WebSocketExpectEventOptions) (interface{}, error) {
+ return ws.expectEvent(event, cb, options...)
+}
+
+func (ws *webSocketImpl) WaitForEvent(event string, options ...WebSocketWaitForEventOptions) (interface{}, error) {
+ if len(options) == 1 {
+ option := WebSocketExpectEventOptions(options[0])
+ return ws.expectEvent(event, nil, option)
+ } else {
+ return ws.expectEvent(event, nil)
+ }
+}
+
+func (ws *webSocketImpl) expectEvent(event string, cb func() error, options ...WebSocketExpectEventOptions) (interface{}, error) {
+ var predicate interface{} = nil
+ timeout := ws.page.timeoutSettings.Timeout()
+ if len(options) == 1 {
+ if options[0].Timeout != nil {
+ timeout = *options[0].Timeout
+ }
+ if options[0].Predicate != nil {
+ predicate = options[0].Predicate
+ }
+ }
+ waiter := newWaiter().WithTimeout(timeout)
+ if event != "close" {
+ waiter.RejectOnEvent(ws, "close", errors.New("websocket closed"))
+ }
+ if event != "socketerror" {
+ waiter.RejectOnEvent(ws, "socketerror", errors.New("websocket error"))
+ }
+ waiter.RejectOnEvent(ws.page, "close", errors.New("page closed"))
+ if cb == nil {
+ return waiter.WaitForEvent(ws, event, predicate).Wait()
+ } else {
+ return waiter.WaitForEvent(ws, event, predicate).RunAndWait(cb)
+ }
+}
+
+func (ws *webSocketImpl) IsClosed() bool {
+ ws.RLock()
+ defer ws.RUnlock()
+ return ws.isClosed
+}
+
+func (ws *webSocketImpl) OnClose(fn func(WebSocket)) {
+ ws.On("close", fn)
+}
+
+func (ws *webSocketImpl) OnFrameReceived(fn func(payload []byte)) {
+ ws.On("framereceived", fn)
+}
+
+func (ws *webSocketImpl) OnFrameSent(fn func(payload []byte)) {
+ ws.On("framesent", fn)
+}
+
+func (ws *webSocketImpl) OnSocketError(fn func(string)) {
+ ws.On("socketerror", fn)
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/websocket_route.go b/vendor/github.com/playwright-community/playwright-go/websocket_route.go
new file mode 100644
index 0000000..bb74ab9
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/websocket_route.go
@@ -0,0 +1,220 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "fmt"
+ "regexp"
+ "sync/atomic"
+)
+
+type webSocketRouteImpl struct {
+ channelOwner
+ connected *atomic.Bool
+ server WebSocketRoute
+ onPageMessage func(interface{})
+ onPageClose func(code *int, reason *string)
+ onServerMessage func(interface{})
+ onServerClose func(code *int, reason *string)
+}
+
+func newWebSocketRoute(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *webSocketRouteImpl {
+ route := &webSocketRouteImpl{
+ connected: &atomic.Bool{},
+ }
+ route.createChannelOwner(route, parent, objectType, guid, initializer)
+ route.markAsInternalType()
+
+ route.server = newServerWebSocketRoute(route)
+
+ route.channel.On("messageFromPage", func(event map[string]interface{}) {
+ msg, err := untransformWebSocketMessage(event)
+ if err != nil {
+ panic(fmt.Errorf("Could not decode WebSocket message: %w", err))
+ }
+ if route.onPageMessage != nil {
+ route.onPageMessage(msg)
+ } else if route.connected.Load() {
+ go route.channel.SendNoReply("sendToServer", event)
+ }
+ })
+
+ route.channel.On("messageFromServer", func(event map[string]interface{}) {
+ msg, err := untransformWebSocketMessage(event)
+ if err != nil {
+ panic(fmt.Errorf("Could not decode WebSocket message: %w", err))
+ }
+ if route.onServerMessage != nil {
+ route.onServerMessage(msg)
+ } else {
+ go route.channel.SendNoReply("sendToPage", event)
+ }
+ })
+
+ route.channel.On("closePage", func(event map[string]interface{}) {
+ if route.onPageClose != nil {
+ route.onPageClose(event["code"].(*int), event["reason"].(*string))
+ } else {
+ go route.channel.SendNoReply("closeServer", event)
+ }
+ })
+
+ route.channel.On("closeServer", func(event map[string]interface{}) {
+ if route.onServerClose != nil {
+ route.onServerClose(event["code"].(*int), event["reason"].(*string))
+ } else {
+ go route.channel.SendNoReply("closePage", event)
+ }
+ })
+
+ return route
+}
+
+func (r *webSocketRouteImpl) Close(options ...WebSocketRouteCloseOptions) {
+ r.channel.SendNoReply("closePage", options, map[string]interface{}{"wasClean": true})
+}
+
+func (r *webSocketRouteImpl) ConnectToServer() (WebSocketRoute, error) {
+ if r.connected.Load() {
+ return nil, fmt.Errorf("Already connected to the server")
+ }
+ r.channel.SendNoReply("connect")
+ r.connected.Store(true)
+ return r.server, nil
+}
+
+func (r *webSocketRouteImpl) OnClose(handler func(code *int, reason *string)) {
+ r.onPageClose = handler
+}
+
+func (r *webSocketRouteImpl) OnMessage(handler func(interface{})) {
+ r.onPageMessage = handler
+}
+
+func (r *webSocketRouteImpl) Send(message interface{}) {
+ data, err := transformWebSocketMessage(message)
+ if err != nil {
+ panic(fmt.Errorf("Could not encode WebSocket message: %w", err))
+ }
+ go r.channel.SendNoReply("sendToPage", data)
+}
+
+func (r *webSocketRouteImpl) URL() string {
+ return r.initializer["url"].(string)
+}
+
+func (r *webSocketRouteImpl) afterHandle() error {
+ if r.connected.Load() {
+ return nil
+ }
+ // Ensure that websocket is "open" and can send messages without an actual server connection.
+ _, err := r.channel.Send("ensureOpened")
+ return err
+}
+
+type serverWebSocketRouteImpl struct {
+ webSocketRoute *webSocketRouteImpl
+}
+
+func newServerWebSocketRoute(route *webSocketRouteImpl) *serverWebSocketRouteImpl {
+ return &serverWebSocketRouteImpl{webSocketRoute: route}
+}
+
+func (s *serverWebSocketRouteImpl) OnMessage(handler func(interface{})) {
+ s.webSocketRoute.onServerMessage = handler
+}
+
+func (s *serverWebSocketRouteImpl) OnClose(handler func(code *int, reason *string)) {
+ s.webSocketRoute.onServerClose = handler
+}
+
+func (s *serverWebSocketRouteImpl) ConnectToServer() (WebSocketRoute, error) {
+ return nil, fmt.Errorf("ConnectToServer must be called on the page-side WebSocketRoute")
+}
+
+func (s *serverWebSocketRouteImpl) URL() string {
+ return s.webSocketRoute.URL()
+}
+
+func (s *serverWebSocketRouteImpl) Close(options ...WebSocketRouteCloseOptions) {
+ go s.webSocketRoute.channel.SendNoReply("close", options, map[string]interface{}{"wasClean": true})
+}
+
+func (s *serverWebSocketRouteImpl) Send(message interface{}) {
+ data, err := transformWebSocketMessage(message)
+ if err != nil {
+ panic(fmt.Errorf("Could not encode WebSocket message: %w", err))
+ }
+ go s.webSocketRoute.channel.SendNoReply("sendToServer", data)
+}
+
+func transformWebSocketMessage(message interface{}) (map[string]interface{}, error) {
+ data := map[string]interface{}{}
+ switch v := message.(type) {
+ case []byte:
+ data["isBase64"] = true
+ data["message"] = base64.StdEncoding.EncodeToString(v)
+ case string:
+ data["isBase64"] = false
+ data["message"] = v
+ default:
+ return nil, fmt.Errorf("Unsupported message type: %T", v)
+ }
+ return data, nil
+}
+
+func untransformWebSocketMessage(data map[string]interface{}) (interface{}, error) {
+ if data["isBase64"].(bool) {
+ return base64.StdEncoding.DecodeString(data["message"].(string))
+ }
+ return data["message"], nil
+}
+
+type webSocketRouteHandler struct {
+ matcher *urlMatcher
+ handler func(WebSocketRoute)
+}
+
+func newWebSocketRouteHandler(matcher *urlMatcher, handler func(WebSocketRoute)) *webSocketRouteHandler {
+ return &webSocketRouteHandler{matcher: matcher, handler: handler}
+}
+
+func (h *webSocketRouteHandler) Handle(route WebSocketRoute) {
+ h.handler(route)
+ err := route.(*webSocketRouteImpl).afterHandle()
+ if err != nil {
+ panic(fmt.Errorf("Could not handle WebSocketRoute: %w", err))
+ }
+}
+
+func (h *webSocketRouteHandler) Matches(wsURL string) bool {
+ return h.matcher.Matches(wsURL)
+}
+
+func prepareWebSocketRouteHandlerInterceptionPatterns(handlers []*webSocketRouteHandler) []map[string]interface{} {
+ patterns := []map[string]interface{}{}
+ all := false
+ for _, handler := range handlers {
+ switch handler.matcher.raw.(type) {
+ case *regexp.Regexp:
+ pattern, flags := convertRegexp(handler.matcher.raw.(*regexp.Regexp))
+ patterns = append(patterns, map[string]interface{}{
+ "regexSource": pattern,
+ "regexFlags": flags,
+ })
+ case string:
+ patterns = append(patterns, map[string]interface{}{
+ "glob": handler.matcher.raw.(string),
+ })
+ default:
+ all = true
+ }
+ }
+ if all {
+ return []map[string]interface{}{
+ {
+ "glob": "**/*",
+ },
+ }
+ }
+ return patterns
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/worker.go b/vendor/github.com/playwright-community/playwright-go/worker.go
new file mode 100644
index 0000000..6504385
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/worker.go
@@ -0,0 +1,78 @@
+package playwright
+
+type workerImpl struct {
+ channelOwner
+ page *pageImpl
+ context *browserContextImpl
+}
+
+func (w *workerImpl) URL() string {
+ return w.initializer["url"].(string)
+}
+
+func (w *workerImpl) Evaluate(expression string, options ...interface{}) (interface{}, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := w.channel.Send("evaluateExpression", map[string]interface{}{
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(result), nil
+}
+
+func (w *workerImpl) EvaluateHandle(expression string, options ...interface{}) (JSHandle, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := w.channel.Send("evaluateExpressionHandle", map[string]interface{}{
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(result).(*jsHandleImpl), nil
+}
+
+func (w *workerImpl) onClose() {
+ if w.page != nil {
+ w.page.Lock()
+ workers := make([]Worker, 0)
+ for i := 0; i < len(w.page.workers); i++ {
+ if w.page.workers[i] != w {
+ workers = append(workers, w.page.workers[i])
+ }
+ }
+ w.page.workers = workers
+ w.page.Unlock()
+ }
+ if w.context != nil {
+ w.context.Lock()
+ workers := make([]Worker, 0)
+ for i := 0; i < len(w.context.serviceWorkers); i++ {
+ if w.context.serviceWorkers[i] != w {
+ workers = append(workers, w.context.serviceWorkers[i])
+ }
+ }
+ w.context.serviceWorkers = workers
+ w.context.Unlock()
+ }
+ w.Emit("close", w)
+}
+
+func (w *workerImpl) OnClose(fn func(Worker)) {
+ w.On("close", fn)
+}
+
+func newWorker(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *workerImpl {
+ bt := &workerImpl{}
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ bt.channel.On("close", bt.onClose)
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/writable_stream.go b/vendor/github.com/playwright-community/playwright-go/writable_stream.go
new file mode 100644
index 0000000..7f144b4
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/writable_stream.go
@@ -0,0 +1,44 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "io"
+ "os"
+)
+
+type writableStream struct {
+ channelOwner
+}
+
+func (s *writableStream) Copy(file string) error {
+ f, err := os.OpenFile(file, os.O_RDONLY, 0)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ for {
+ buf := make([]byte, defaultCopyBufSize)
+ n, err := f.Read(buf)
+ if err != nil && err != io.EOF {
+ return err
+ }
+ if n == 0 {
+ break
+ }
+ _, err = s.channel.Send("write", map[string]interface{}{
+ "binary": base64.StdEncoding.EncodeToString(buf[:n]),
+ })
+ if err != nil {
+ return err
+ }
+ }
+ _, err = s.channel.Send("close")
+ return err
+}
+
+func newWritableStream(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *writableStream {
+ stream := &writableStream{}
+ stream.createChannelOwner(stream, parent, objectType, guid, initializer)
+ return stream
+}
diff --git a/vendor/github.com/power-devops/perfstat/config.go b/vendor/github.com/power-devops/perfstat/config.go
index de7230d..a6df39c 100644
--- a/vendor/github.com/power-devops/perfstat/config.go
+++ b/vendor/github.com/power-devops/perfstat/config.go
@@ -1,3 +1,4 @@
+//go:build aix
// +build aix
package perfstat
diff --git a/vendor/github.com/power-devops/perfstat/cpustat.go b/vendor/github.com/power-devops/perfstat/cpustat.go
index 902727f..10f543f 100644
--- a/vendor/github.com/power-devops/perfstat/cpustat.go
+++ b/vendor/github.com/power-devops/perfstat/cpustat.go
@@ -1,3 +1,4 @@
+//go:build aix
// +build aix
package perfstat
@@ -20,6 +21,13 @@ import (
"unsafe"
)
+var old_cpu_total_stat *C.perfstat_cpu_total_t
+
+func init() {
+ old_cpu_total_stat = (*C.perfstat_cpu_total_t)(C.malloc(C.sizeof_perfstat_cpu_total_t))
+ C.perfstat_cpu_total(nil, old_cpu_total_stat, C.sizeof_perfstat_cpu_total_t, 1)
+}
+
func CpuStat() ([]CPU, error) {
var cpustat *C.perfstat_cpu_t
var cpu C.perfstat_id_t
@@ -96,3 +104,35 @@ func CpuUtilStat(intvl time.Duration) (*CPUUtil, error) {
u := perfstatcpuutil2cpuutil(cpuutil)
return &u, nil
}
+
+func CpuUtilTotalStat() (*CPUUtil, error) {
+ var cpuutil *C.perfstat_cpu_util_t
+ var new_cpu_total_stat *C.perfstat_cpu_total_t
+ var data C.perfstat_rawdata_t
+
+ new_cpu_total_stat = (*C.perfstat_cpu_total_t)(C.malloc(C.sizeof_perfstat_cpu_total_t))
+ cpuutil = (*C.perfstat_cpu_util_t)(C.malloc(C.sizeof_perfstat_cpu_util_t))
+ defer C.free(unsafe.Pointer(cpuutil))
+
+ r := C.perfstat_cpu_total(nil, new_cpu_total_stat, C.sizeof_perfstat_cpu_total_t, 1)
+ if r <= 0 {
+ C.free(unsafe.Pointer(new_cpu_total_stat))
+ return nil, fmt.Errorf("error perfstat_cpu_total()")
+ }
+
+ data._type = C.UTIL_CPU_TOTAL
+ data.curstat = unsafe.Pointer(new_cpu_total_stat)
+ data.prevstat = unsafe.Pointer(old_cpu_total_stat)
+ data.sizeof_data = C.sizeof_perfstat_cpu_total_t
+ data.cur_elems = 1
+ data.prev_elems = 1
+
+ r = C.perfstat_cpu_util(&data, cpuutil, C.sizeof_perfstat_cpu_util_t, 1)
+ C.free(unsafe.Pointer(old_cpu_total_stat))
+ old_cpu_total_stat = new_cpu_total_stat
+ if r <= 0 {
+ return nil, fmt.Errorf("error perfstat_cpu_util()")
+ }
+ u := perfstatcpuutil2cpuutil(cpuutil)
+ return &u, nil
+}
diff --git a/vendor/github.com/power-devops/perfstat/diskstat.go b/vendor/github.com/power-devops/perfstat/diskstat.go
index fc70dfa..06763b4 100644
--- a/vendor/github.com/power-devops/perfstat/diskstat.go
+++ b/vendor/github.com/power-devops/perfstat/diskstat.go
@@ -1,3 +1,4 @@
+//go:build aix
// +build aix
package perfstat
diff --git a/vendor/github.com/power-devops/perfstat/doc.go b/vendor/github.com/power-devops/perfstat/doc.go
index 85eaf3e..9730a61 100644
--- a/vendor/github.com/power-devops/perfstat/doc.go
+++ b/vendor/github.com/power-devops/perfstat/doc.go
@@ -1,3 +1,4 @@
+//go:build !aix
// +build !aix
// Copyright 2020 Power-Devops.com. All rights reserved.
@@ -36,24 +37,24 @@ func DisableLVMStat() {}
// CpuStat() returns array of CPU structures with information about
// logical CPUs on the system.
// IBM documentation:
-// * https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_int_cpu.html
-// * https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cpu.html
+// - https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_int_cpu.html
+// - https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cpu.html
func CpuStat() ([]CPU, error) {
return nil, fmt.Errorf("not implemented")
}
// CpuTotalStat() returns general information about CPUs on the system.
// IBM documentation:
-// * https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_glob_cpu.html
-// * https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cputot.html
+// - https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_glob_cpu.html
+// - https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cputot.html
func CpuTotalStat() (*CPUTotal, error) {
return nil, fmt.Errorf("not implemented")
}
// CpuUtilStat() calculates CPU utilization.
// IBM documentation:
-// * https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_cpu_util.html
-// * https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cpu_util.html
+// - https://www.ibm.com/support/knowledgecenter/ssw_aix_72/performancetools/idprftools_perfstat_cpu_util.html
+// - https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/p_bostechref/perfstat_cpu_util.html
func CpuUtilStat(intvl time.Duration) (*CPUUtil, error) {
return nil, fmt.Errorf("not implemented")
}
diff --git a/vendor/github.com/power-devops/perfstat/fsstat.go b/vendor/github.com/power-devops/perfstat/fsstat.go
index 27f4c06..d391319 100644
--- a/vendor/github.com/power-devops/perfstat/fsstat.go
+++ b/vendor/github.com/power-devops/perfstat/fsstat.go
@@ -1,3 +1,4 @@
+//go:build aix
// +build aix
package perfstat
diff --git a/vendor/github.com/power-devops/perfstat/helpers.go b/vendor/github.com/power-devops/perfstat/helpers.go
index e8d6997..d5268ab 100644
--- a/vendor/github.com/power-devops/perfstat/helpers.go
+++ b/vendor/github.com/power-devops/perfstat/helpers.go
@@ -1,3 +1,4 @@
+//go:build aix
// +build aix
package perfstat
@@ -7,6 +8,7 @@ package perfstat
#include <libperfstat.h>
#include <sys/proc.h>
+#include <sys/dr.h>
#include "c_helpers.h"
*/
@@ -754,7 +756,7 @@ func fsinfo2filesystem(n *C.struct_fsinfo) FileSystem {
i.Device = C.GoString(n.devname)
i.MountPoint = C.GoString(n.fsname)
i.FSType = int(n.fstype)
- i.Flags = int(n.flags)
+ i.Flags = uint(n.flags)
i.TotalBlocks = int64(n.totalblks)
i.FreeBlocks = int64(n.freeblks)
i.TotalInodes = int64(n.totalinodes)
@@ -762,3 +764,56 @@ func fsinfo2filesystem(n *C.struct_fsinfo) FileSystem {
return i
}
+
+func lparinfo2partinfo(n C.lpar_info_format2_t) PartitionInfo {
+ var i PartitionInfo
+
+ i.Version = int(n.version)
+ i.OnlineMemory = uint64(n.online_memory)
+ i.TotalDispatchTime = uint64(n.tot_dispatch_time)
+ i.PoolIdleTime = uint64(n.pool_idle_time)
+ i.DispatchLatency = uint64(n.dispatch_latency)
+ i.LparFlags = uint(n.lpar_flags)
+ i.PCpusInSys = uint(n.pcpus_in_sys)
+ i.OnlineVCpus = uint(n.online_vcpus)
+ i.OnlineLCpus = uint(n.online_lcpus)
+ i.PCpusInPool = uint(n.pcpus_in_pool)
+ i.UnallocCapacity = uint(n.unalloc_capacity)
+ i.EntitledCapacity = uint(n.entitled_capacity)
+ i.VariableWeight = uint(n.variable_weight)
+ i.UnallocWeight = uint(n.unalloc_weight)
+ i.MinReqVCpuCapacity = uint(n.min_req_vcpu_capacity)
+ i.GroupId = uint8(n.group_id)
+ i.PoolId = uint8(n.pool_id)
+ i.ShCpusInSys = uint(n.shcpus_in_sys)
+ i.MaxPoolCapacity = uint(n.max_pool_capacity)
+ i.EntitledPoolCapacity = uint(n.entitled_pool_capacity)
+ i.PoolMaxTime = uint64(n.pool_max_time)
+ i.PoolBusyTime = uint64(n.pool_busy_time)
+ i.PoolScaledBusyTime = uint64(n.pool_scaled_busy_time)
+ i.ShCpuTotalTime = uint64(n.shcpu_tot_time)
+ i.ShCpuBusyTime = uint64(n.shcpu_busy_time)
+ i.ShCpuScaledBusyTime = uint64(n.shcpu_scaled_busy_time)
+ i.EntMemCapacity = uint64(n.ent_mem_capacity)
+ i.PhysMem = uint64(n.phys_mem)
+ i.VrmPoolPhysMem = uint64(n.vrm_pool_physmem)
+ i.HypPageSize = uint(n.hyp_pagesize)
+ i.VrmPoolId = int(n.vrm_pool_id)
+ i.VrmGroupId = int(n.vrm_group_id)
+ i.VarMemWeight = int(n.var_mem_weight)
+ i.UnallocVarMemWeight = int(n.unalloc_var_mem_weight)
+ i.UnallocEntMemCapacity = uint64(n.unalloc_ent_mem_capacity)
+ i.TrueOnlineMemory = uint64(n.true_online_memory)
+ i.AmeOnlineMemory = uint64(n.ame_online_memory)
+ i.AmeType = uint8(n.ame_type)
+ i.SpecExecMode = uint8(n.spec_exec_mode)
+ i.AmeFactor = uint(n.ame_factor)
+ i.EmPartMajorCode = uint(n.em_part_major_code)
+ i.EmPartMinorCode = uint(n.em_part_minor_code)
+ i.BytesCoalesced = uint64(n.bytes_coalesced)
+ i.BytesCoalescedMemPool = uint64(n.bytes_coalesced_mempool)
+ i.PurrCoalescing = uint64(n.purr_coalescing)
+ i.SpurrCoalescing = uint64(n.spurr_coalescing)
+
+ return i
+}
diff --git a/vendor/github.com/power-devops/perfstat/lparstat.go b/vendor/github.com/power-devops/perfstat/lparstat.go
index 0ce35e3..470a1af 100644
--- a/vendor/github.com/power-devops/perfstat/lparstat.go
+++ b/vendor/github.com/power-devops/perfstat/lparstat.go
@@ -1,3 +1,4 @@
+//go:build aix
// +build aix
package perfstat
@@ -6,11 +7,13 @@ package perfstat
#cgo LDFLAGS: -lperfstat
#include <libperfstat.h>
+#include <sys/dr.h>
*/
import "C"
import (
"fmt"
+ "unsafe"
)
func PartitionStat() (*PartitionConfig, error) {
@@ -24,3 +27,14 @@ func PartitionStat() (*PartitionConfig, error) {
return &p, nil
}
+
+func LparInfo() (*PartitionInfo, error) {
+ var pinfo C.lpar_info_format2_t
+
+ rc := C.lpar_get_info(C.LPAR_INFO_FORMAT2, unsafe.Pointer(&pinfo), C.sizeof_lpar_info_format2_t)
+ if rc != 0 {
+ return nil, fmt.Errorf("lpar_get_info() error")
+ }
+ p := lparinfo2partinfo(pinfo)
+ return &p, nil
+}
diff --git a/vendor/github.com/power-devops/perfstat/lvmstat.go b/vendor/github.com/power-devops/perfstat/lvmstat.go
index eb2064c..2ce9908 100644
--- a/vendor/github.com/power-devops/perfstat/lvmstat.go
+++ b/vendor/github.com/power-devops/perfstat/lvmstat.go
@@ -1,3 +1,4 @@
+//go:build aix
// +build aix
package perfstat
diff --git a/vendor/github.com/power-devops/perfstat/memstat.go b/vendor/github.com/power-devops/perfstat/memstat.go
index d211a73..52133f0 100644
--- a/vendor/github.com/power-devops/perfstat/memstat.go
+++ b/vendor/github.com/power-devops/perfstat/memstat.go
@@ -1,3 +1,4 @@
+//go:build aix
// +build aix
package perfstat
diff --git a/vendor/github.com/power-devops/perfstat/netstat.go b/vendor/github.com/power-devops/perfstat/netstat.go
index 4070da2..847d294 100644
--- a/vendor/github.com/power-devops/perfstat/netstat.go
+++ b/vendor/github.com/power-devops/perfstat/netstat.go
@@ -1,3 +1,4 @@
+//go:build aix
// +build aix
package perfstat
diff --git a/vendor/github.com/power-devops/perfstat/procstat.go b/vendor/github.com/power-devops/perfstat/procstat.go
index ecafebd..957ec2b 100644
--- a/vendor/github.com/power-devops/perfstat/procstat.go
+++ b/vendor/github.com/power-devops/perfstat/procstat.go
@@ -1,3 +1,4 @@
+//go:build aix
// +build aix
package perfstat
diff --git a/vendor/github.com/power-devops/perfstat/sysconf.go b/vendor/github.com/power-devops/perfstat/sysconf.go
index c7454d0..b557da0 100644
--- a/vendor/github.com/power-devops/perfstat/sysconf.go
+++ b/vendor/github.com/power-devops/perfstat/sysconf.go
@@ -1,3 +1,4 @@
+//go:build aix
// +build aix
package perfstat
diff --git a/vendor/github.com/power-devops/perfstat/systemcfg.go b/vendor/github.com/power-devops/perfstat/systemcfg.go
index 6287eb4..b7c7b72 100644
--- a/vendor/github.com/power-devops/perfstat/systemcfg.go
+++ b/vendor/github.com/power-devops/perfstat/systemcfg.go
@@ -1,3 +1,4 @@
+//go:build aix
// +build aix
package perfstat
@@ -70,6 +71,7 @@ const (
SC_TM_VER = 59 /* Transaction Memory version, 0 - not capable */
SC_NX_CAP = 60 /* NX GZIP capable */
SC_PKS_STATE = 61 /* Platform KeyStore */
+ SC_MMA_VER = 62
)
/* kernel attributes */
@@ -119,6 +121,7 @@ const (
IMPL_POWER7 = 0x8000 /* 7 class CPU */
IMPL_POWER8 = 0x10000 /* 8 class CPU */
IMPL_POWER9 = 0x20000 /* 9 class CPU */
+ IMPL_POWER10 = 0x20000 /* 10 class CPU */
)
// Values for implementation field for IA64 Architectures
@@ -151,11 +154,13 @@ const (
PV_7 = 0x200000 /* Power PC 7 */
PV_8 = 0x300000 /* Power PC 8 */
PV_9 = 0x400000 /* Power PC 9 */
+ PV_10 = 0x500000 /* Power PC 10 */
PV_5_Compat = 0x0F8000 /* Power PC 5 */
PV_6_Compat = 0x108000 /* Power PC 6 */
PV_7_Compat = 0x208000 /* Power PC 7 */
PV_8_Compat = 0x308000 /* Power PC 8 */
PV_9_Compat = 0x408000 /* Power PC 9 */
+ PV_10_Compat = 0x508000 /* Power PC 10 */
PV_RESERVED_2 = 0x0A0000 /* source compatability */
PV_RESERVED_3 = 0x0B0000 /* source compatability */
PV_RS2 = 0x040000 /* Power RS2 */
@@ -181,19 +186,21 @@ const (
// Macros for identifying physical processor
const (
- PPI4_1 = 0x35
- PPI4_2 = 0x38
- PPI4_3 = 0x39
- PPI4_4 = 0x3C
- PPI4_5 = 0x44
- PPI5_1 = 0x3A
- PPI5_2 = 0x3B
- PPI6_1 = 0x3E
- PPI7_1 = 0x3F
- PPI7_2 = 0x4A
- PPI8_1 = 0x4B
- PPI8_2 = 0x4D
- PPI9 = 0x4E
+ PPI4_1 = 0x35
+ PPI4_2 = 0x38
+ PPI4_3 = 0x39
+ PPI4_4 = 0x3C
+ PPI4_5 = 0x44
+ PPI5_1 = 0x3A
+ PPI5_2 = 0x3B
+ PPI6_1 = 0x3E
+ PPI7_1 = 0x3F
+ PPI7_2 = 0x4A
+ PPI8_1 = 0x4B
+ PPI8_2 = 0x4D
+ PPI9 = 0x4E
+ PPI9_1 = 0x4E
+ PPI10_1 = 0x80
)
// Macros for kernel attributes
@@ -291,14 +298,32 @@ func GetCPUImplementation() string {
return "POWER8"
case impl&IMPL_POWER9 != 0:
return "POWER9"
+ case impl&IMPL_POWER10 != 0:
+ return "Power10"
default:
return "Unknown"
}
}
+func POWER10OrNewer() bool {
+ impl := unix.Getsystemcfg(SC_IMPL)
+ if impl&IMPL_POWER10 != 0 {
+ return true
+ }
+ return false
+}
+
+func POWER10() bool {
+ impl := unix.Getsystemcfg(SC_IMPL)
+ if impl&IMPL_POWER10 != 0 {
+ return true
+ }
+ return false
+}
+
func POWER9OrNewer() bool {
impl := unix.Getsystemcfg(SC_IMPL)
- if impl&IMPL_POWER9 != 0 {
+ if impl&IMPL_POWER10 != 0 || impl&IMPL_POWER9 != 0 {
return true
}
return false
@@ -314,7 +339,7 @@ func POWER9() bool {
func POWER8OrNewer() bool {
impl := unix.Getsystemcfg(SC_IMPL)
- if impl&IMPL_POWER9 != 0 || impl&IMPL_POWER8 != 0 {
+ if impl&IMPL_POWER10 != 0 || impl&IMPL_POWER9 != 0 || impl&IMPL_POWER8 != 0 {
return true
}
return false
@@ -330,7 +355,7 @@ func POWER8() bool {
func POWER7OrNewer() bool {
impl := unix.Getsystemcfg(SC_IMPL)
- if impl&IMPL_POWER9 != 0 || impl&IMPL_POWER8 != 0 || impl&IMPL_POWER7 != 0 {
+ if impl&IMPL_POWER10 != 0 || impl&IMPL_POWER9 != 0 || impl&IMPL_POWER8 != 0 || impl&IMPL_POWER7 != 0 {
return true
}
return false
@@ -419,6 +444,8 @@ func PksEnabled() bool {
func CPUMode() string {
impl := unix.Getsystemcfg(SC_VERS)
switch impl {
+ case PV_10, PV_10_Compat:
+ return "Power10"
case PV_9, PV_9_Compat:
return "POWER9"
case PV_8, PV_8_Compat:
diff --git a/vendor/github.com/power-devops/perfstat/types_disk.go b/vendor/github.com/power-devops/perfstat/types_disk.go
index ca1493d..50e323d 100644
--- a/vendor/github.com/power-devops/perfstat/types_disk.go
+++ b/vendor/github.com/power-devops/perfstat/types_disk.go
@@ -29,8 +29,8 @@ type DiskTotal struct {
// Disk Adapter Types
const (
DA_SCSI = 0 /* 0 ==> SCSI, SAS, other legacy adapter types */
- DA_VSCSI /* 1 ==> Virtual SCSI/SAS Adapter */
- DA_FCA /* 2 ==> Fiber Channel Adapter */
+ DA_VSCSI = 1 /* 1 ==> Virtual SCSI/SAS Adapter */
+ DA_FCA = 2 /* 2 ==> Fiber Channel Adapter */
)
type DiskAdapter struct {
diff --git a/vendor/github.com/power-devops/perfstat/types_fs.go b/vendor/github.com/power-devops/perfstat/types_fs.go
index 0be048a..b4b43ac 100644
--- a/vendor/github.com/power-devops/perfstat/types_fs.go
+++ b/vendor/github.com/power-devops/perfstat/types_fs.go
@@ -8,7 +8,7 @@ type FileSystem struct {
Device string /* name of the mounted device */
MountPoint string /* where the device is mounted */
FSType int /* File system type, see the constants below */
- Flags int /* Flags of the file system */
+ Flags uint /* Flags of the file system */
TotalBlocks int64 /* number of 512 bytes blocks in the filesystem */
FreeBlocks int64 /* number of free 512 bytes block in the filesystem */
TotalInodes int64 /* total number of inodes in the filesystem */
diff --git a/vendor/github.com/power-devops/perfstat/types_lpar.go b/vendor/github.com/power-devops/perfstat/types_lpar.go
index 2d3c32f..f95f8c3 100644
--- a/vendor/github.com/power-devops/perfstat/types_lpar.go
+++ b/vendor/github.com/power-devops/perfstat/types_lpar.go
@@ -66,3 +66,64 @@ type PartitionConfig struct {
TargetMemExpSize int64 /* Expanded Memory Size in MB */
SubProcessorMode int32 /* Split core mode, its value can be 0,1,2 or 4. 0 for unsupported, 1 for capable but not enabled, 2 or 4 for enabled*/
}
+
+const (
+ AME_TYPE_V1 = 0x1
+ AME_TYPE_V2 = 0x2
+ LPAR_INFO_CAPPED = 0x01 /* Parition Capped */
+ LPAR_INFO_AUTH_PIC = 0x02 /* Authority granted for poolidle*/
+ LPAR_INFO_SMT_ENABLED = 0x04 /* SMT Enabled */
+ LPAR_INFO_WPAR_ACTIVE = 0x08 /* Process Running Within a WPAR */
+ LPAR_INFO_EXTENDED = 0x10 /* Extended shared processor pool information */
+ LPAR_INFO_AME_ENABLED = 0x20 /* Active Mem. Expansion (AME) enabled*/
+ LPAR_INFO_SEM_ENABLED = 0x40 /* Speculative Execution Mode enabled */
+)
+
+type PartitionInfo struct {
+ Version int /* version for this structure */
+ OnlineMemory uint64 /* MB of currently online memory */
+ TotalDispatchTime uint64 /* Total lpar dispatch time in nsecs */
+ PoolIdleTime uint64 /* Idle time of shared CPU pool nsecs*/
+ DispatchLatency uint64 /* Max latency inbetween dispatches of this LPAR on physCPUS in nsecs */
+ LparFlags uint /* LPAR flags */
+ PCpusInSys uint /* # of active licensed physical CPUs in system */
+ OnlineVCpus uint /* # of current online virtual CPUs */
+ OnlineLCpus uint /* # of current online logical CPUs */
+ PCpusInPool uint /* # physical CPUs in shared pool */
+ UnallocCapacity uint /* Unallocated Capacity available in shared pool */
+ EntitledCapacity uint /* Entitled Processor Capacity for this partition */
+ VariableWeight uint /* Variable Processor Capacity Weight */
+ UnallocWeight uint /* Unallocated Variable Weight available for this partition */
+ MinReqVCpuCapacity uint /* OS minimum required virtual processor capacity. */
+ GroupId uint8 /* ID of a LPAR group/aggregation */
+ PoolId uint8 /* ID of a shared pool */
+ ShCpusInSys uint /* # of physical processors allocated for shared processor use */
+ MaxPoolCapacity uint /* Maximum processor capacity of partition's pool */
+ EntitledPoolCapacity uint /* Entitled processor capacity of partition's pool */
+ PoolMaxTime uint64 /* Summation of maximum time that could be consumed by the pool, in nanoseconds */
+ PoolBusyTime uint64 /* Summation of busy time accumulated across all partitions in the pool, in nanoseconds */
+ PoolScaledBusyTime uint64 /* Scaled summation of busy time accumulated across all partitions in the pool, in nanoseconds */
+ ShCpuTotalTime uint64 /* Summation of total time across all physical processors allocated for shared processor use, in nanoseconds */
+ ShCpuBusyTime uint64 /* Summation of busy time accumulated across all shared processor partitions, in nanoseconds */
+ ShCpuScaledBusyTime uint64 /* Scaled summation of busy time accumulated across all shared processor partitions, in nanoseconds */
+ EntMemCapacity uint64 /* Partition's current entitlement memory capacity setting */
+ PhysMem uint64 /* Amount of physical memory, in bytes, currently backing the partition's logical memory */
+ VrmPoolPhysMem uint64 /* Total amount of physical memory in the VRM pool */
+ HypPageSize uint /* Page size hypervisor is using to virtualize partition's memory */
+ VrmPoolId int /* ID of VRM pool */
+ VrmGroupId int /* eWLM VRM group to which partition belongs */
+ VarMemWeight int /* Partition's current variable memory capacity weighting setting */
+ UnallocVarMemWeight int /* Amount of unallocated variable memory capacity weight available to LPAR's group */
+ UnallocEntMemCapacity uint64 /* Amount of unallocated I/O memory entitlement available to LPAR's group */
+ TrueOnlineMemory uint64 /* true MB of currently online memory */
+ AmeOnlineMemory uint64 /* AME MB of currently online memory */
+ AmeType uint8
+ SpecExecMode uint8 /* Speculative Execution Mode */
+ AmeFactor uint /* memory expansion factor for LPAR */
+ EmPartMajorCode uint /* Major and minor codes for our */
+ EmPartMinorCode uint /* current energy management mode */
+ BytesCoalesced uint64 /* The number of bytes of the calling partition.s logical real memory coalesced because they contained duplicated data */
+ BytesCoalescedMemPool uint64 /* If the calling partition is authorized to see pool wide statistics then the number of bytes of logical real memory coalesced because they contained duplicated data in the calling partition.s memory pool else set to zero.*/
+ PurrCoalescing uint64 /* If the calling partition is authorized to see pool wide statistics then PURR cycles consumed to coalesce data else set to zero.*/
+ SpurrCoalescing uint64 /* If the calling partition is authorized to see pool wide statistics then SPURR cycles consumed to coalesce data else set to zero.*/
+}
diff --git a/vendor/github.com/power-devops/perfstat/uptime.go b/vendor/github.com/power-devops/perfstat/uptime.go
index 2bd3e56..8608787 100644
--- a/vendor/github.com/power-devops/perfstat/uptime.go
+++ b/vendor/github.com/power-devops/perfstat/uptime.go
@@ -1,3 +1,4 @@
+//go:build aix
// +build aix
package perfstat
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_aix_nocgo.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_aix_nocgo.go
index 329ef83..981e32e 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_aix_nocgo.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_aix_nocgo.go
@@ -14,11 +14,11 @@ import (
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
var ret []TimesStat
if percpu {
- per_out, err := invoke.CommandWithContext(ctx, "sar", "-u", "-P", "ALL", "10", "1")
+ perOut, err := invoke.CommandWithContext(ctx, "sar", "-u", "-P", "ALL", "10", "1")
if err != nil {
return nil, err
}
- lines := strings.Split(string(per_out), "\n")
+ lines := strings.Split(string(perOut), "\n")
if len(lines) < 6 {
return []TimesStat{}, common.ErrNotImplementedError
}
@@ -105,14 +105,15 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
ret := InfoStat{}
for _, line := range strings.Split(string(out), "\n") {
- if strings.HasPrefix(line, "Number Of Processors:") {
+ switch {
+ case strings.HasPrefix(line, "Number Of Processors:"):
p := strings.Fields(line)
if len(p) > 3 {
if t, err := strconv.ParseUint(p[3], 10, 64); err == nil {
ret.Cores = int32(t)
}
}
- } else if strings.HasPrefix(line, "Processor Clock Speed:") {
+ case strings.HasPrefix(line, "Processor Clock Speed:"):
p := strings.Fields(line)
if len(p) > 4 {
if t, err := strconv.ParseFloat(p[3], 64); err == nil {
@@ -128,13 +129,12 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
}
}
}
- break
- } else if strings.HasPrefix(line, "System Model:") {
+ case strings.HasPrefix(line, "System Model:"):
p := strings.Split(string(line), ":")
if p != nil {
ret.VendorID = strings.TrimSpace(p[1])
}
- } else if strings.HasPrefix(line, "Processor Type:") {
+ case strings.HasPrefix(line, "Processor Type:"):
p := strings.Split(string(line), ":")
if p != nil {
c := strings.Split(string(p[1]), "_")
@@ -148,7 +148,7 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
return []InfoStat{ret}, nil
}
-func CountsWithContext(ctx context.Context, logical bool) (int, error) {
+func CountsWithContext(ctx context.Context, _ bool) (int, error) {
info, err := InfoWithContext(ctx)
if err == nil {
return int(info[0].Cores), nil
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_darwin.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_darwin.go
index b3e3a66..c61a470 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_darwin.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_darwin.go
@@ -5,6 +5,7 @@ package cpu
import (
"context"
+ "errors"
"fmt"
"strconv"
"strings"
@@ -37,10 +38,10 @@ const (
// mach/processor_info.h
const (
- processorCpuLoadInfo = 2
+ processorCpuLoadInfo = 2 //nolint:revive //FIXME
)
-type hostCpuLoadInfoData struct {
+type hostCpuLoadInfoData struct { //nolint:revive //FIXME
cpuTicks [cpuStateMax]uint32
}
@@ -59,7 +60,7 @@ func Times(percpu bool) ([]TimesStat, error) {
return TimesWithContext(context.Background(), percpu)
}
-func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
+func TimesWithContext(_ context.Context, percpu bool) ([]TimesStat, error) {
lib, err := common.NewLibrary(common.System)
if err != nil {
return nil, err
@@ -78,7 +79,7 @@ func Info() ([]InfoStat, error) {
return InfoWithContext(context.Background())
}
-func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
+func InfoWithContext(_ context.Context) ([]InfoStat, error) {
var ret []InfoStat
c := InfoStat{}
@@ -121,7 +122,7 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
return append(ret, c), nil
}
-func CountsWithContext(ctx context.Context, logical bool) (int, error) {
+func CountsWithContext(_ context.Context, logical bool) (int, error) {
var cpuArgument string
if logical {
cpuArgument = "hw.logicalcpu"
@@ -152,6 +153,10 @@ func perCPUTimes(machLib *common.Library) ([]TimesStat, error) {
return nil, fmt.Errorf("host_processor_info error=%d", status)
}
+ if cpuload == nil {
+ return nil, errors.New("host_processor_info returned nil cpuload")
+ }
+
defer vmDeallocate(machTaskSelf(), uintptr(unsafe.Pointer(cpuload)), uintptr(ncpu))
ret := []TimesStat{}
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_dragonfly.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_dragonfly.go
index 19b1e9d..8232c48 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_dragonfly.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_dragonfly.go
@@ -11,9 +11,10 @@ import (
"strings"
"unsafe"
- "github.com/shirou/gopsutil/v4/internal/common"
"github.com/tklauser/go-sysconf"
"golang.org/x/sys/unix"
+
+ "github.com/shirou/gopsutil/v4/internal/common"
)
var (
@@ -50,7 +51,7 @@ func Times(percpu bool) ([]TimesStat, error) {
return TimesWithContext(context.Background(), percpu)
}
-func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
+func TimesWithContext(_ context.Context, percpu bool) ([]TimesStat, error) {
if percpu {
buf, err := unix.SysctlRaw("kern.cp_times")
if err != nil {
@@ -91,7 +92,7 @@ func Info() ([]InfoStat, error) {
return InfoWithContext(context.Background())
}
-func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
+func InfoWithContext(_ context.Context) ([]InfoStat, error) {
const dmesgBoot = "/var/run/dmesg.boot"
c, err := parseDmesgBoot(dmesgBoot)
@@ -135,7 +136,7 @@ func parseDmesgBoot(fileName string) (InfoStat, error) {
c.VendorID = matches[1]
t, err := strconv.ParseInt(matches[2], 10, 32)
if err != nil {
- return c, fmt.Errorf("unable to parse DragonflyBSD CPU stepping information from %q: %v", line, err)
+ return c, fmt.Errorf("unable to parse DragonflyBSD CPU stepping information from %q: %w", line, err)
}
c.Stepping = int32(t)
} else if matches := featuresMatch.FindStringSubmatch(line); matches != nil {
@@ -152,6 +153,6 @@ func parseDmesgBoot(fileName string) (InfoStat, error) {
return c, nil
}
-func CountsWithContext(ctx context.Context, logical bool) (int, error) {
+func CountsWithContext(_ context.Context, _ bool) (int, error) {
return runtime.NumCPU(), nil
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_freebsd.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_freebsd.go
index 5d17c7e..107b574 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_freebsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_freebsd.go
@@ -52,7 +52,7 @@ func Times(percpu bool) ([]TimesStat, error) {
return TimesWithContext(context.Background(), percpu)
}
-func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
+func TimesWithContext(_ context.Context, percpu bool) ([]TimesStat, error) {
if percpu {
buf, err := unix.SysctlRaw("kern.cp_times")
if err != nil {
@@ -93,7 +93,7 @@ func Info() ([]InfoStat, error) {
return InfoWithContext(context.Background())
}
-func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
+func InfoWithContext(_ context.Context) ([]InfoStat, error) {
const dmesgBoot = "/var/run/dmesg.boot"
c, num, err := parseDmesgBoot(dmesgBoot)
@@ -165,6 +165,6 @@ func parseDmesgBoot(fileName string) (InfoStat, int, error) {
return c, cpuNum, nil
}
-func CountsWithContext(ctx context.Context, logical bool) (int, error) {
+func CountsWithContext(_ context.Context, _ bool) (int, error) {
return runtime.NumCPU(), nil
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_linux.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_linux.go
index 5f595e7..a3c60ff 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_linux.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_linux.go
@@ -157,7 +157,7 @@ func finishCPUInfo(ctx context.Context, c *InfoStat) {
}
c.Mhz = value / 1000.0 // value is in kHz
if c.Mhz > 9999 {
- c.Mhz = c.Mhz / 1000.0 // value in Hz
+ c.Mhz /= 1000.0 // value in Hz
}
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_netbsd.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_netbsd.go
index 198be5e..cc76985 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_netbsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_netbsd.go
@@ -36,7 +36,7 @@ func Times(percpu bool) ([]TimesStat, error) {
return TimesWithContext(context.Background(), percpu)
}
-func TimesWithContext(ctx context.Context, percpu bool) (ret []TimesStat, err error) {
+func TimesWithContext(_ context.Context, percpu bool) (ret []TimesStat, err error) {
if !percpu {
mib := []int32{ctlKern, kernCpTime}
buf, _, err := common.CallSyscall(mib)
@@ -57,7 +57,7 @@ func TimesWithContext(ctx context.Context, percpu bool) (ret []TimesStat, err er
ncpu, err := unix.SysctlUint32("hw.ncpu")
if err != nil {
- return
+ return //nolint:nakedret //FIXME
}
var i uint32
@@ -87,7 +87,7 @@ func Info() ([]InfoStat, error) {
return InfoWithContext(context.Background())
}
-func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
+func InfoWithContext(_ context.Context) ([]InfoStat, error) {
var ret []InfoStat
var err error
@@ -115,6 +115,6 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
return append(ret, c), nil
}
-func CountsWithContext(ctx context.Context, logical bool) (int, error) {
+func CountsWithContext(_ context.Context, _ bool) (int, error) {
return runtime.NumCPU(), nil
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_openbsd.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_openbsd.go
index 33233d3..9038a4d 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_openbsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_openbsd.go
@@ -9,9 +9,10 @@ import (
"runtime"
"unsafe"
- "github.com/shirou/gopsutil/v4/internal/common"
"github.com/tklauser/go-sysconf"
"golang.org/x/sys/unix"
+
+ "github.com/shirou/gopsutil/v4/internal/common"
)
const (
@@ -53,7 +54,7 @@ func Times(percpu bool) ([]TimesStat, error) {
return TimesWithContext(context.Background(), percpu)
}
-func TimesWithContext(ctx context.Context, percpu bool) (ret []TimesStat, err error) {
+func TimesWithContext(_ context.Context, percpu bool) (ret []TimesStat, err error) {
if !percpu {
mib := []int32{ctlKern, kernCpTime}
buf, _, err := common.CallSyscall(mib)
@@ -74,7 +75,7 @@ func TimesWithContext(ctx context.Context, percpu bool) (ret []TimesStat, err er
ncpu, err := unix.SysctlUint32("hw.ncpu")
if err != nil {
- return
+ return //nolint:nakedret //FIXME
}
var i uint32
@@ -107,7 +108,7 @@ func Info() ([]InfoStat, error) {
return InfoWithContext(context.Background())
}
-func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
+func InfoWithContext(_ context.Context) ([]InfoStat, error) {
var ret []InfoStat
var err error
@@ -132,6 +133,6 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
return append(ret, c), nil
}
-func CountsWithContext(ctx context.Context, logical bool) (int, error) {
+func CountsWithContext(_ context.Context, _ bool) (int, error) {
return runtime.NumCPU(), nil
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_plan9.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_plan9.go
index bff2e0c..02ad3f7 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_plan9.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_plan9.go
@@ -9,6 +9,7 @@ import (
"runtime"
stats "github.com/lufia/plan9stats"
+
"github.com/shirou/gopsutil/v4/internal/common"
)
@@ -16,7 +17,7 @@ func Times(percpu bool) ([]TimesStat, error) {
return TimesWithContext(context.Background(), percpu)
}
-func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
+func TimesWithContext(ctx context.Context, _ bool) ([]TimesStat, error) {
// BUG: percpu flag is not supported yet.
root := os.Getenv("HOST_ROOT")
c, err := stats.ReadCPUType(ctx, stats.WithRootDir(root))
@@ -41,10 +42,10 @@ func Info() ([]InfoStat, error) {
return InfoWithContext(context.Background())
}
-func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
+func InfoWithContext(_ context.Context) ([]InfoStat, error) {
return []InfoStat{}, common.ErrNotImplementedError
}
-func CountsWithContext(ctx context.Context, logical bool) (int, error) {
+func CountsWithContext(_ context.Context, _ bool) (int, error) {
return runtime.NumCPU(), nil
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_solaris.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_solaris.go
index d8ba1d3..1911c0f 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_solaris.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_solaris.go
@@ -42,7 +42,7 @@ var kstatSplit = regexp.MustCompile(`[:\s]+`)
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
kstatSysOut, err := invoke.CommandWithContext(ctx, "kstat", "-p", "cpu_stat:*:*:/^idle$|^user$|^kernel$|^iowait$|^swap$/")
if err != nil {
- return nil, fmt.Errorf("cannot execute kstat: %s", err)
+ return nil, fmt.Errorf("cannot execute kstat: %w", err)
}
cpu := make(map[float64]float64)
idle := make(map[float64]float64)
@@ -57,31 +57,31 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
}
cpuNumber, err := strconv.ParseFloat(fields[1], 64)
if err != nil {
- return nil, fmt.Errorf("cannot parse cpu number: %s", err)
+ return nil, fmt.Errorf("cannot parse cpu number: %w", err)
}
cpu[cpuNumber] = cpuNumber
switch fields[3] {
case "idle":
idle[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
if err != nil {
- return nil, fmt.Errorf("cannot parse idle: %s", err)
+ return nil, fmt.Errorf("cannot parse idle: %w", err)
}
case "user":
user[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
if err != nil {
- return nil, fmt.Errorf("cannot parse user: %s", err)
+ return nil, fmt.Errorf("cannot parse user: %w", err)
}
case "kernel":
kern[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
if err != nil {
- return nil, fmt.Errorf("cannot parse kernel: %s", err)
+ return nil, fmt.Errorf("cannot parse kernel: %w", err)
}
case "iowait":
iowt[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
if err != nil {
- return nil, fmt.Errorf("cannot parse iowait: %s", err)
+ return nil, fmt.Errorf("cannot parse iowait: %w", err)
}
- //not sure how this translates, don't report, add to kernel, something else?
+ // not sure how this translates, don't report, add to kernel, something else?
/*case "swap":
swap[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
if err != nil {
@@ -121,22 +121,22 @@ func Info() ([]InfoStat, error) {
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
psrInfoOut, err := invoke.CommandWithContext(ctx, "psrinfo", "-p", "-v")
if err != nil {
- return nil, fmt.Errorf("cannot execute psrinfo: %s", err)
+ return nil, fmt.Errorf("cannot execute psrinfo: %w", err)
}
procs, err := parseProcessorInfo(string(psrInfoOut))
if err != nil {
- return nil, fmt.Errorf("error parsing psrinfo output: %s", err)
+ return nil, fmt.Errorf("error parsing psrinfo output: %w", err)
}
isaInfoOut, err := invoke.CommandWithContext(ctx, "isainfo", "-b", "-v")
if err != nil {
- return nil, fmt.Errorf("cannot execute isainfo: %s", err)
+ return nil, fmt.Errorf("cannot execute isainfo: %w", err)
}
flags, err := parseISAInfo(string(isaInfoOut))
if err != nil {
- return nil, fmt.Errorf("error parsing isainfo output: %s", err)
+ return nil, fmt.Errorf("error parsing isainfo output: %w", err)
}
result := make([]InfoStat, 0, len(flags))
@@ -160,7 +160,7 @@ func parseISAInfo(cmdOutput string) ([]string, error) {
}
flags := make([]string, len(words)-4)
- for i, val := range words[4:] {
+ for i, val := range words[4:] { //nolint:gosimple //FIXME
flags[i] = val
}
sort.Strings(flags)
@@ -194,7 +194,7 @@ func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) {
if physicalCPU[psrStepOffset] != "" {
stepParsed, err := strconv.ParseInt(physicalCPU[psrStepOffset], 10, 32)
if err != nil {
- return nil, fmt.Errorf("cannot parse value %q for step as 32-bit integer: %s", physicalCPU[9], err)
+ return nil, fmt.Errorf("cannot parse value %q for step as 32-bit integer: %w", physicalCPU[9], err)
}
step = int32(stepParsed)
}
@@ -202,7 +202,7 @@ func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) {
if physicalCPU[psrClockOffset] != "" {
clockParsed, err := strconv.ParseInt(physicalCPU[psrClockOffset], 10, 64)
if err != nil {
- return nil, fmt.Errorf("cannot parse value %q for clock as 32-bit integer: %s", physicalCPU[10], err)
+ return nil, fmt.Errorf("cannot parse value %q for clock as 32-bit integer: %w", physicalCPU[10], err)
}
clock = float64(clockParsed)
}
@@ -214,7 +214,7 @@ func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) {
case physicalCPU[psrNumCoresOffset] != "":
numCores, err = strconv.ParseInt(physicalCPU[psrNumCoresOffset], 10, 32)
if err != nil {
- return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %s", physicalCPU[1], err)
+ return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %w", physicalCPU[1], err)
}
for i := 0; i < int(numCores); i++ {
@@ -235,12 +235,12 @@ func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) {
case physicalCPU[psrNumCoresHTOffset] != "":
numCores, err = strconv.ParseInt(physicalCPU[psrNumCoresHTOffset], 10, 32)
if err != nil {
- return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %s", physicalCPU[3], err)
+ return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %w", physicalCPU[3], err)
}
numHT, err = strconv.ParseInt(physicalCPU[psrNumHTOffset], 10, 32)
if err != nil {
- return nil, fmt.Errorf("cannot parse value %q for hyperthread count as 32-bit integer: %s", physicalCPU[4], err)
+ return nil, fmt.Errorf("cannot parse value %q for hyperthread count as 32-bit integer: %w", physicalCPU[4], err)
}
for i := 0; i < int(numCores); i++ {
@@ -265,6 +265,6 @@ func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) {
return result, nil
}
-func CountsWithContext(ctx context.Context, logical bool) (int, error) {
+func CountsWithContext(_ context.Context, _ bool) (int, error) {
return runtime.NumCPU(), nil
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_windows.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_windows.go
index 4476b91..de86c04 100644
--- a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_windows.go
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_windows.go
@@ -6,16 +6,18 @@ package cpu
import (
"context"
"fmt"
+ "strconv"
"unsafe"
- "github.com/shirou/gopsutil/v4/internal/common"
"github.com/yusufpapurcu/wmi"
"golang.org/x/sys/windows"
+
+ "github.com/shirou/gopsutil/v4/internal/common"
)
var procGetNativeSystemInfo = common.Modkernel32.NewProc("GetNativeSystemInfo")
-type win32_Processor struct {
+type win32_Processor struct { //nolint:revive //FIXME
Family uint16
Manufacturer string
Name string
@@ -31,13 +33,13 @@ type win32_Processor struct {
// https://docs.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntquerysysteminformation#system_processor_performance_information
// additional fields documented here
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/processor_performance.htm
-type win32_SystemProcessorPerformanceInformation struct {
- IdleTime int64 // idle time in 100ns (this is not a filetime).
- KernelTime int64 // kernel time in 100ns. kernel time includes idle time. (this is not a filetime).
- UserTime int64 // usertime in 100ns (this is not a filetime).
- DpcTime int64 // dpc time in 100ns (this is not a filetime).
- InterruptTime int64 // interrupt time in 100ns
- InterruptCount uint32
+type win32_SystemProcessorPerformanceInformation struct { //nolint:revive //FIXME
+ IdleTime int64 // idle time in 100ns (this is not a filetime).
+ KernelTime int64 // kernel time in 100ns. kernel time includes idle time. (this is not a filetime).
+ UserTime int64 // usertime in 100ns (this is not a filetime).
+ DpcTime int64 // dpc time in 100ns (this is not a filetime).
+ InterruptTime int64 // interrupt time in 100ns
+ InterruptCount uint64 // ULONG needs to be uint64
}
const (
@@ -45,10 +47,10 @@ const (
// systemProcessorPerformanceInformationClass information class to query with NTQuerySystemInformation
// https://processhacker.sourceforge.io/doc/ntexapi_8h.html#ad5d815b48e8f4da1ef2eb7a2f18a54e0
- win32_SystemProcessorPerformanceInformationClass = 8
+ win32_SystemProcessorPerformanceInformationClass = 8 //nolint:revive //FIXME
// size of systemProcessorPerformanceInfoSize in memory
- win32_SystemProcessorPerformanceInfoSize = uint32(unsafe.Sizeof(win32_SystemProcessorPerformanceInformation{}))
+ win32_SystemProcessorPerformanceInfoSize = uint32(unsafe.Sizeof(win32_SystemProcessorPerformanceInformation{})) //nolint:revive //FIXME
)
// Times returns times stat per cpu and combined for all CPUs
@@ -56,7 +58,7 @@ func Times(percpu bool) ([]TimesStat, error) {
return TimesWithContext(context.Background(), percpu)
}
-func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
+func TimesWithContext(_ context.Context, percpu bool) ([]TimesStat, error) {
if percpu {
return perCPUTimes()
}
@@ -110,7 +112,7 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
cpu := InfoStat{
CPU: int32(i),
- Family: fmt.Sprintf("%d", l.Family),
+ Family: strconv.FormatUint(uint64(l.Family), 10),
VendorID: l.Manufacturer,
ModelName: l.Name,
Cores: int32(l.NumberOfLogicalProcessors),
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/binary.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/binary.go
index 6e75e74..11a4fd4 100644
--- a/vendor/github.com/shirou/gopsutil/v4/internal/common/binary.go
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/binary.go
@@ -137,7 +137,7 @@ func (bigEndian) GoString() string { return "binary.BigEndian" }
// blank (_) field names is skipped; i.e., blank field names
// may be used for padding.
// When reading into a struct, all non-blank fields must be exported.
-func Read(r io.Reader, order ByteOrder, data interface{}) error {
+func Read(r io.Reader, order ByteOrder, data any) error {
// Fast path for basic types and slices.
if n := intDataSize(data); n != 0 {
var b [8]byte
@@ -229,7 +229,7 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error {
// and read from successive fields of the data.
// When writing structs, zero values are written for fields
// with blank (_) field names.
-func Write(w io.Writer, order ByteOrder, data interface{}) error {
+func Write(w io.Writer, order ByteOrder, data any) error {
// Fast path for basic types and slices.
if n := intDataSize(data); n != 0 {
var b [8]byte
@@ -339,7 +339,7 @@ func Write(w io.Writer, order ByteOrder, data interface{}) error {
// Size returns how many bytes Write would generate to encode the value v, which
// must be a fixed-size value or a slice of fixed-size values, or a pointer to such data.
// If v is neither of these, Size returns -1.
-func Size(v interface{}) int {
+func Size(v any) int {
return dataSize(reflect.Indirect(reflect.ValueOf(v)))
}
@@ -607,7 +607,7 @@ func (e *encoder) skip(v reflect.Value) {
// intDataSize returns the size of the data required to represent the data when encoded.
// It returns zero if the type cannot be implemented by the fast path in Read or Write.
-func intDataSize(data interface{}) int {
+func intDataSize(data any) int {
switch data := data.(type) {
case int8, *int8, *uint8:
return 1
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/common.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/common.go
index 868ea4d..4f9b2f7 100644
--- a/vendor/github.com/shirou/gopsutil/v4/internal/common/common.go
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/common.go
@@ -31,8 +31,9 @@ import (
)
var (
- Timeout = 3 * time.Second
- ErrTimeout = errors.New("command timed out")
+ Timeout = 3 * time.Second
+ ErrNotImplementedError = errors.New("not implemented yet")
+ ErrTimeout = errors.New("command timed out")
)
type Invoker interface {
@@ -93,12 +94,10 @@ func (i FakeInvoke) Command(name string, arg ...string) ([]byte, error) {
return []byte{}, fmt.Errorf("could not find testdata: %s", fpath)
}
-func (i FakeInvoke) CommandWithContext(ctx context.Context, name string, arg ...string) ([]byte, error) {
+func (i FakeInvoke) CommandWithContext(_ context.Context, name string, arg ...string) ([]byte, error) {
return i.Command(name, arg...)
}
-var ErrNotImplementedError = errors.New("not implemented yet")
-
// ReadFile reads contents from a file
func ReadFile(filename string) (string, error) {
content, err := os.ReadFile(filename)
@@ -311,7 +310,7 @@ func IntContains(target []int, src int) bool {
// get struct attributes.
// This method is used only for debugging platform dependent code.
-func attributes(m interface{}) map[string]reflect.Type {
+func attributes(m any) map[string]reflect.Type {
typ := reflect.TypeOf(m)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_darwin.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_darwin.go
index 2de3bb1..afa780d 100644
--- a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_darwin.go
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_darwin.go
@@ -5,6 +5,7 @@ package common
import (
"context"
+ "errors"
"fmt"
"os"
"os/exec"
@@ -306,7 +307,7 @@ const (
func NewSMC(ioKit *Library) (*SMC, error) {
if ioKit.path != IOKit {
- return nil, fmt.Errorf("library is not IOKit")
+ return nil, errors.New("library is not IOKit")
}
ioServiceGetMatchingService := GetFunc[IOServiceGetMatchingServiceFunc](ioKit, IOServiceGetMatchingServiceSym)
@@ -324,7 +325,7 @@ func NewSMC(ioKit *Library) (*SMC, error) {
var conn uint32
if result := ioServiceOpen(service, machTaskSelf(), 0, &conn); result != 0 {
- return nil, fmt.Errorf("ERROR: IOServiceOpen failed")
+ return nil, errors.New("ERROR: IOServiceOpen failed")
}
ioObjectRelease(service)
@@ -343,7 +344,7 @@ func (s *SMC) Close() error {
ioServiceClose := GetFunc[IOServiceCloseFunc](s.lib, IOServiceCloseSym)
if result := ioServiceClose(s.conn); result != 0 {
- return fmt.Errorf("ERROR: IOServiceClose failed")
+ return errors.New("ERROR: IOServiceClose failed")
}
return nil
}
@@ -367,8 +368,8 @@ func (s CStr) Ptr() *byte {
return &s[0]
}
-func (c CStr) Addr() uintptr {
- return uintptr(unsafe.Pointer(c.Ptr()))
+func (s CStr) Addr() uintptr {
+ return uintptr(unsafe.Pointer(s.Ptr()))
}
func (s CStr) GoString() string {
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_linux.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_linux.go
index 277034f..04ec171 100644
--- a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_linux.go
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_linux.go
@@ -196,19 +196,20 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
if PathExists(filename) {
contents, err := ReadLines(filename)
if err == nil {
- if StringsContains(contents, "kvm") {
+ switch {
+ case StringsContains(contents, "kvm"):
system = "kvm"
role = "host"
- } else if StringsContains(contents, "hv_util") {
+ case StringsContains(contents, "hv_util"):
system = "hyperv"
role = "guest"
- } else if StringsContains(contents, "vboxdrv") {
+ case StringsContains(contents, "vboxdrv"):
system = "vbox"
role = "host"
- } else if StringsContains(contents, "vboxguest") {
+ case StringsContains(contents, "vboxguest"):
system = "vbox"
role = "guest"
- } else if StringsContains(contents, "vmware") {
+ case StringsContains(contents, "vmware"):
system = "vmware"
role = "guest"
}
@@ -273,16 +274,17 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
if PathExists(filepath.Join(filename, "self", "cgroup")) {
contents, err := ReadLines(filepath.Join(filename, "self", "cgroup"))
if err == nil {
- if StringsContains(contents, "lxc") {
+ switch {
+ case StringsContains(contents, "lxc"):
system = "lxc"
role = "guest"
- } else if StringsContains(contents, "docker") {
+ case StringsContains(contents, "docker"):
system = "docker"
role = "guest"
- } else if StringsContains(contents, "machine-rkt") {
+ case StringsContains(contents, "machine-rkt"):
system = "rkt"
role = "guest"
- } else if PathExists("/usr/bin/lxc-version") {
+ case PathExists("/usr/bin/lxc-version"):
system = "lxc"
role = "host"
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_testing.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_testing.go
new file mode 100644
index 0000000..55f36f1
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_testing.go
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package common
+
+import (
+ "errors"
+ "testing"
+)
+
+func SkipIfNotImplementedErr(tb testing.TB, err error) {
+ tb.Helper()
+ if errors.Is(err, ErrNotImplementedError) {
+ tb.Skip("not implemented")
+ }
+}
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_windows.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_windows.go
index 766ed2f..f3ec5a9 100644
--- a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_windows.go
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_windows.go
@@ -17,19 +17,19 @@ import (
)
// for double values
-type PDH_FMT_COUNTERVALUE_DOUBLE struct {
+type PDH_FMT_COUNTERVALUE_DOUBLE struct { //nolint:revive //FIXME
CStatus uint32
DoubleValue float64
}
// for 64 bit integer values
-type PDH_FMT_COUNTERVALUE_LARGE struct {
+type PDH_FMT_COUNTERVALUE_LARGE struct { //nolint:revive //FIXME
CStatus uint32
LargeValue int64
}
// for long values
-type PDH_FMT_COUNTERVALUE_LONG struct {
+type PDH_FMT_COUNTERVALUE_LONG struct { //nolint:revive //FIXME
CStatus uint32
LongValue int32
padding [4]byte
@@ -197,7 +197,7 @@ func ProcessorQueueLengthCounter() (*Win32PerformanceCounter, error) {
}
// WMIQueryWithContext - wraps wmi.Query with a timed-out context to avoid hanging
-func WMIQueryWithContext(ctx context.Context, query string, dst interface{}, connectServerArgs ...interface{}) error {
+func WMIQueryWithContext(ctx context.Context, query string, dst any, connectServerArgs ...any) error {
if _, ok := ctx.Deadline(); !ok {
ctxTimeout, cancel := context.WithTimeout(ctx, Timeout)
defer cancel()
@@ -233,7 +233,7 @@ func ConvertDOSPath(p string) string {
ret, _, _ := procQueryDosDeviceW.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(szDeviceName))),
uintptr(unsafe.Pointer(&szTarget[0])),
uintptr(len(szTarget)))
- if ret != 0 && windows.UTF16ToString(szTarget[:]) == rawDrive {
+ if ret != 0 && windows.UTF16ToString(szTarget) == rawDrive {
return filepath.Join(szDeviceName, p[len(rawDrive):])
}
}
@@ -273,19 +273,19 @@ type SystemExtendedHandleInformation struct {
// CallWithExpandingBuffer https://github.com/hillu/go-ntdll
func CallWithExpandingBuffer(fn func() NtStatus, buf *[]byte, resultLength *uint32) NtStatus {
for {
- if st := fn(); st == STATUS_BUFFER_OVERFLOW || st == STATUS_BUFFER_TOO_SMALL || st == STATUS_INFO_LENGTH_MISMATCH {
+ st := fn()
+ if st == STATUS_BUFFER_OVERFLOW || st == STATUS_BUFFER_TOO_SMALL || st == STATUS_INFO_LENGTH_MISMATCH {
if int(*resultLength) <= cap(*buf) {
(*reflect.SliceHeader)(unsafe.Pointer(buf)).Len = int(*resultLength)
} else {
*buf = make([]byte, int(*resultLength))
}
continue
- } else {
- if !st.IsError() {
- *buf = (*buf)[:int(*resultLength)]
- }
- return st
}
+ if !st.IsError() {
+ *buf = (*buf)[:int(*resultLength)]
+ }
+ return st
}
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/mem/mem_darwin.go b/vendor/github.com/shirou/gopsutil/v4/mem/mem_darwin.go
index a4c15f6..7d96a3b 100644
--- a/vendor/github.com/shirou/gopsutil/v4/mem/mem_darwin.go
+++ b/vendor/github.com/shirou/gopsutil/v4/mem/mem_darwin.go
@@ -35,7 +35,7 @@ func SwapMemory() (*SwapMemoryStat, error) {
return SwapMemoryWithContext(context.Background())
}
-func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
+func SwapMemoryWithContext(_ context.Context) (*SwapMemoryStat, error) {
// https://github.com/yanllearnn/go-osstat/blob/ae8a279d26f52ec946a03698c7f50a26cfb427e3/memory/memory_darwin.go
var ret *SwapMemoryStat
@@ -67,7 +67,7 @@ func SwapDevices() ([]*SwapDevice, error) {
return SwapDevicesWithContext(context.Background())
}
-func SwapDevicesWithContext(ctx context.Context) ([]*SwapDevice, error) {
+func SwapDevicesWithContext(_ context.Context) ([]*SwapDevice, error) {
return nil, common.ErrNotImplementedError
}
@@ -84,7 +84,7 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
return VirtualMemoryWithContext(context.Background())
}
-func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
+func VirtualMemoryWithContext(_ context.Context) (*VirtualMemoryStat, error) {
machLib, err := common.NewLibrary(common.System)
if err != nil {
return nil, err
diff --git a/vendor/github.com/shirou/gopsutil/v4/mem/mem_fallback.go b/vendor/github.com/shirou/gopsutil/v4/mem/mem_fallback.go
index ba882c8..74283a2 100644
--- a/vendor/github.com/shirou/gopsutil/v4/mem/mem_fallback.go
+++ b/vendor/github.com/shirou/gopsutil/v4/mem/mem_fallback.go
@@ -13,7 +13,7 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
return VirtualMemoryWithContext(context.Background())
}
-func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
+func VirtualMemoryWithContext(_ context.Context) (*VirtualMemoryStat, error) {
return nil, common.ErrNotImplementedError
}
@@ -21,7 +21,7 @@ func SwapMemory() (*SwapMemoryStat, error) {
return SwapMemoryWithContext(context.Background())
}
-func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
+func SwapMemoryWithContext(_ context.Context) (*SwapMemoryStat, error) {
return nil, common.ErrNotImplementedError
}
@@ -29,6 +29,6 @@ func SwapDevices() ([]*SwapDevice, error) {
return SwapDevicesWithContext(context.Background())
}
-func SwapDevicesWithContext(ctx context.Context) ([]*SwapDevice, error) {
+func SwapDevicesWithContext(_ context.Context) ([]*SwapDevice, error) {
return nil, common.ErrNotImplementedError
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/mem/mem_freebsd.go b/vendor/github.com/shirou/gopsutil/v4/mem/mem_freebsd.go
index a6dedde..dbe6d91 100644
--- a/vendor/github.com/shirou/gopsutil/v4/mem/mem_freebsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/mem/mem_freebsd.go
@@ -17,7 +17,7 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
return VirtualMemoryWithContext(context.Background())
}
-func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
+func VirtualMemoryWithContext(_ context.Context) (*VirtualMemoryStat, error) {
pageSize, err := common.SysctlUint("vm.stats.vm.v_page_size")
if err != nil {
return nil, err
@@ -110,7 +110,7 @@ type xswdev11 struct {
Used int32 // Used is the number of blocks used
}
-func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
+func SwapMemoryWithContext(_ context.Context) (*SwapMemoryStat, error) {
// FreeBSD can have multiple swap devices so we total them up
i, err := common.SysctlUint("vm.nswapdev")
if err != nil {
@@ -139,7 +139,8 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
// first, try to parse with version 2
xsw := (*xswdev)(unsafe.Pointer(&buf[0]))
- if xsw.Version == XSWDEV_VERSION11 {
+ switch {
+ case xsw.Version == XSWDEV_VERSION11:
// this is version 1, so try to parse again
xsw := (*xswdev11)(unsafe.Pointer(&buf[0]))
if xsw.Version != XSWDEV_VERSION11 {
@@ -147,9 +148,9 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
}
s.Total += uint64(xsw.NBlks)
s.Used += uint64(xsw.Used)
- } else if xsw.Version != XSWDEV_VERSION {
+ case xsw.Version != XSWDEV_VERSION:
return nil, errors.New("xswdev version mismatch")
- } else {
+ default:
s.Total += uint64(xsw.NBlks)
s.Used += uint64(xsw.Used)
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/mem/mem_linux.go b/vendor/github.com/shirou/gopsutil/v4/mem/mem_linux.go
index 05bfdaf..3e6e4e3 100644
--- a/vendor/github.com/shirou/gopsutil/v4/mem/mem_linux.go
+++ b/vendor/github.com/shirou/gopsutil/v4/mem/mem_linux.go
@@ -50,7 +50,7 @@ func fillFromMeminfoWithContext(ctx context.Context) (*VirtualMemoryStat, *ExVir
}
key := strings.TrimSpace(fields[0])
value := strings.TrimSpace(fields[1])
- value = strings.Replace(value, " kB", "", -1)
+ value = strings.ReplaceAll(value, " kB", "")
switch key {
case "MemTotal":
diff --git a/vendor/github.com/shirou/gopsutil/v4/mem/mem_netbsd.go b/vendor/github.com/shirou/gopsutil/v4/mem/mem_netbsd.go
index 0a41b3e..8ef539c 100644
--- a/vendor/github.com/shirou/gopsutil/v4/mem/mem_netbsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/mem/mem_netbsd.go
@@ -15,7 +15,7 @@ func GetPageSize() (uint64, error) {
return GetPageSizeWithContext(context.Background())
}
-func GetPageSizeWithContext(ctx context.Context) (uint64, error) {
+func GetPageSizeWithContext(_ context.Context) (uint64, error) {
uvmexp, err := unix.SysctlUvmexp("vm.uvmexp2")
if err != nil {
return 0, err
@@ -27,7 +27,7 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
return VirtualMemoryWithContext(context.Background())
}
-func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
+func VirtualMemoryWithContext(_ context.Context) (*VirtualMemoryStat, error) {
uvmexp, err := unix.SysctlUvmexp("vm.uvmexp2")
if err != nil {
return nil, err
diff --git a/vendor/github.com/shirou/gopsutil/v4/mem/mem_openbsd.go b/vendor/github.com/shirou/gopsutil/v4/mem/mem_openbsd.go
index 2510bb0..680cad1 100644
--- a/vendor/github.com/shirou/gopsutil/v4/mem/mem_openbsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/mem/mem_openbsd.go
@@ -10,15 +10,16 @@ import (
"errors"
"fmt"
- "github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/unix"
+
+ "github.com/shirou/gopsutil/v4/internal/common"
)
func GetPageSize() (uint64, error) {
return GetPageSizeWithContext(context.Background())
}
-func GetPageSizeWithContext(ctx context.Context) (uint64, error) {
+func GetPageSizeWithContext(_ context.Context) (uint64, error) {
uvmexp, err := unix.SysctlUvmexp("vm.uvmexp")
if err != nil {
return 0, err
@@ -30,7 +31,7 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
return VirtualMemoryWithContext(context.Background())
}
-func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
+func VirtualMemoryWithContext(_ context.Context) (*VirtualMemoryStat, error) {
uvmexp, err := unix.SysctlUvmexp("vm.uvmexp")
if err != nil {
return nil, err
diff --git a/vendor/github.com/shirou/gopsutil/v4/mem/mem_plan9.go b/vendor/github.com/shirou/gopsutil/v4/mem/mem_plan9.go
index c17a102..0df0745 100644
--- a/vendor/github.com/shirou/gopsutil/v4/mem/mem_plan9.go
+++ b/vendor/github.com/shirou/gopsutil/v4/mem/mem_plan9.go
@@ -8,6 +8,7 @@ import (
"os"
stats "github.com/lufia/plan9stats"
+
"github.com/shirou/gopsutil/v4/internal/common"
)
@@ -63,6 +64,6 @@ func SwapDevices() ([]*SwapDevice, error) {
return SwapDevicesWithContext(context.Background())
}
-func SwapDevicesWithContext(ctx context.Context) ([]*SwapDevice, error) {
+func SwapDevicesWithContext(_ context.Context) ([]*SwapDevice, error) {
return nil, common.ErrNotImplementedError
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/mem/mem_solaris.go b/vendor/github.com/shirou/gopsutil/v4/mem/mem_solaris.go
index 06d0d9a..1a391dc 100644
--- a/vendor/github.com/shirou/gopsutil/v4/mem/mem_solaris.go
+++ b/vendor/github.com/shirou/gopsutil/v4/mem/mem_solaris.go
@@ -11,8 +11,9 @@ import (
"strconv"
"strings"
- "github.com/shirou/gopsutil/v4/internal/common"
"github.com/tklauser/go-sysconf"
+
+ "github.com/shirou/gopsutil/v4/internal/common"
)
// VirtualMemory for Solaris is a minimal implementation which only returns
@@ -24,17 +25,17 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
result := &VirtualMemoryStat{}
- zoneName, err := zoneName()
+ zoneName, err := zoneName(ctx)
if err != nil {
return nil, err
}
if zoneName == "global" {
- cap, err := globalZoneMemoryCapacity()
+ capacity, err := globalZoneMemoryCapacity(ctx)
if err != nil {
return nil, err
}
- result.Total = cap
+ result.Total = capacity
freemem, err := globalZoneFreeMemory(ctx)
if err != nil {
return nil, err
@@ -43,11 +44,11 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
result.Free = freemem
result.Used = result.Total - result.Free
} else {
- cap, err := nonGlobalZoneMemoryCapacity()
+ capacity, err := nonGlobalZoneMemoryCapacity(ctx)
if err != nil {
return nil, err
}
- result.Total = cap
+ result.Total = capacity
}
return result, nil
@@ -57,12 +58,11 @@ func SwapMemory() (*SwapMemoryStat, error) {
return SwapMemoryWithContext(context.Background())
}
-func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
+func SwapMemoryWithContext(_ context.Context) (*SwapMemoryStat, error) {
return nil, common.ErrNotImplementedError
}
-func zoneName() (string, error) {
- ctx := context.Background()
+func zoneName(ctx context.Context) (string, error) {
out, err := invoke.CommandWithContext(ctx, "zonename")
if err != nil {
return "", err
@@ -73,8 +73,7 @@ func zoneName() (string, error) {
var globalZoneMemoryCapacityMatch = regexp.MustCompile(`[Mm]emory size: (\d+) Megabytes`)
-func globalZoneMemoryCapacity() (uint64, error) {
- ctx := context.Background()
+func globalZoneMemoryCapacity(ctx context.Context) (uint64, error) {
out, err := invoke.CommandWithContext(ctx, "prtconf")
if err != nil {
return 0, err
@@ -114,8 +113,7 @@ func globalZoneFreeMemory(ctx context.Context) (uint64, error) {
var kstatMatch = regexp.MustCompile(`(\S+)\s+(\S*)`)
-func nonGlobalZoneMemoryCapacity() (uint64, error) {
- ctx := context.Background()
+func nonGlobalZoneMemoryCapacity(ctx context.Context) (uint64, error) {
out, err := invoke.CommandWithContext(ctx, "kstat", "-p", "-c", "zone_memory_cap", "memory_cap:*:*:physcap")
if err != nil {
return 0, err
diff --git a/vendor/github.com/shirou/gopsutil/v4/mem/mem_windows.go b/vendor/github.com/shirou/gopsutil/v4/mem/mem_windows.go
index a94b61f..015c1a1 100644
--- a/vendor/github.com/shirou/gopsutil/v4/mem/mem_windows.go
+++ b/vendor/github.com/shirou/gopsutil/v4/mem/mem_windows.go
@@ -9,8 +9,9 @@ import (
"syscall"
"unsafe"
- "github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows"
+
+ "github.com/shirou/gopsutil/v4/internal/common"
)
var (
@@ -36,7 +37,7 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
return VirtualMemoryWithContext(context.Background())
}
-func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
+func VirtualMemoryWithContext(_ context.Context) (*VirtualMemoryStat, error) {
var memInfo memoryStatusEx
memInfo.cbSize = uint32(unsafe.Sizeof(memInfo))
mem, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memInfo)))
@@ -76,7 +77,7 @@ func SwapMemory() (*SwapMemoryStat, error) {
return SwapMemoryWithContext(context.Background())
}
-func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
+func SwapMemoryWithContext(_ context.Context) (*SwapMemoryStat, error) {
// Use the performance counter to get the swap usage percentage
counter, err := common.NewWin32PerformanceCounter("swap_percentage", `\Paging File(_Total)\% Usage`)
if err != nil {
@@ -150,7 +151,7 @@ func SwapDevices() ([]*SwapDevice, error) {
return SwapDevicesWithContext(context.Background())
}
-func SwapDevicesWithContext(ctx context.Context) ([]*SwapDevice, error) {
+func SwapDevicesWithContext(_ context.Context) ([]*SwapDevice, error) {
pageSizeOnce.Do(func() {
var sysInfo systemInfo
procGetNativeSystemInfo.Call(uintptr(unsafe.Pointer(&sysInfo)))
diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net.go b/vendor/github.com/shirou/gopsutil/v4/net/net.go
index 74af54a..78798c5 100644
--- a/vendor/github.com/shirou/gopsutil/v4/net/net.go
+++ b/vendor/github.com/shirou/gopsutil/v4/net/net.go
@@ -207,7 +207,7 @@ func Interfaces() (InterfaceStatList, error) {
return InterfacesWithContext(context.Background())
}
-func InterfacesWithContext(ctx context.Context) (InterfaceStatList, error) {
+func InterfacesWithContext(_ context.Context) (InterfaceStatList, error) {
is, err := net.Interfaces()
if err != nil {
return nil, err
@@ -255,7 +255,7 @@ func InterfacesWithContext(ctx context.Context) (InterfaceStatList, error) {
return ret, nil
}
-func getIOCountersAll(n []IOCountersStat) ([]IOCountersStat, error) {
+func getIOCountersAll(n []IOCountersStat) []IOCountersStat {
r := IOCountersStat{
Name: "all",
}
@@ -270,7 +270,7 @@ func getIOCountersAll(n []IOCountersStat) ([]IOCountersStat, error) {
r.Dropout += nic.Dropout
}
- return []IOCountersStat{r}, nil
+ return []IOCountersStat{r}
}
// NetIOCounters returns network I/O statistics for every network
diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net_aix.go b/vendor/github.com/shirou/gopsutil/v4/net/net_aix.go
index 9df01e3..a5fa881 100644
--- a/vendor/github.com/shirou/gopsutil/v4/net/net_aix.go
+++ b/vendor/github.com/shirou/gopsutil/v4/net/net_aix.go
@@ -15,23 +15,23 @@ import (
)
// Deprecated: use process.PidsWithContext instead
-func PidsWithContext(ctx context.Context) ([]int32, error) {
+func PidsWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
-func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
- return IOCounters(pernic)
+func IOCountersByFileWithContext(ctx context.Context, pernic bool, _ string) ([]IOCountersStat, error) {
+ return IOCountersWithContext(ctx, pernic)
}
-func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
+func FilterCountersWithContext(_ context.Context) ([]FilterStat, error) {
return nil, common.ErrNotImplementedError
}
-func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
+func ConntrackStatsWithContext(_ context.Context, _ bool) ([]ConntrackStat, error) {
return nil, common.ErrNotImplementedError
}
-func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
+func ProtoCountersWithContext(_ context.Context, _ []string) ([]ProtoCountersStat, error) {
return nil, common.ErrNotImplementedError
}
@@ -193,7 +193,8 @@ func parseNetstatA(output string, kind string) ([]ConnectionStat, error) {
continue
}
- if strings.HasPrefix(fields[0], "f1") {
+ switch {
+ case strings.HasPrefix(fields[0], "f1"):
// Unix lines
if len(fields) < 2 {
// every unix connections have two lines
@@ -202,12 +203,12 @@ func parseNetstatA(output string, kind string) ([]ConnectionStat, error) {
c, err := parseNetstatUnixLine(fields)
if err != nil {
- return nil, fmt.Errorf("failed to parse Unix Address (%s): %s", line, err)
+ return nil, fmt.Errorf("failed to parse Unix Address (%s): %w", line, err)
}
ret = append(ret, c)
- } else if strings.HasPrefix(fields[0], "tcp") || strings.HasPrefix(fields[0], "udp") {
+ case strings.HasPrefix(fields[0], "tcp") || strings.HasPrefix(fields[0], "udp"):
// Inet lines
if !hasCorrectInetProto(kind, fields[0]) {
continue
@@ -221,11 +222,11 @@ func parseNetstatA(output string, kind string) ([]ConnectionStat, error) {
c, err := parseNetstatNetLine(line)
if err != nil {
- return nil, fmt.Errorf("failed to parse Inet Address (%s): %s", line, err)
+ return nil, fmt.Errorf("failed to parse Inet Address (%s): %w", line, err)
}
ret = append(ret, c)
- } else {
+ default:
// Header lines
continue
}
@@ -294,6 +295,6 @@ func ConnectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, p
return connectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, maxConn, true)
}
-func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, maxConn int, skipUids bool) ([]ConnectionStat, error) {
+func connectionsPidMaxWithoutUidsWithContext(_ context.Context, _ string, _ int32, _ int, _ bool) ([]ConnectionStat, error) {
return []ConnectionStat{}, common.ErrNotImplementedError
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net_aix_cgo.go b/vendor/github.com/shirou/gopsutil/v4/net/net_aix_cgo.go
index a45a5b7..f7da4ce 100644
--- a/vendor/github.com/shirou/gopsutil/v4/net/net_aix_cgo.go
+++ b/vendor/github.com/shirou/gopsutil/v4/net/net_aix_cgo.go
@@ -29,8 +29,8 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
}
iocounters = append(iocounters, n)
}
- if pernic == false {
- return getIOCountersAll(iocounters)
+ if !pernic {
+ return getIOCountersAll(iocounters), nil
}
return iocounters, nil
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net_aix_nocgo.go b/vendor/github.com/shirou/gopsutil/v4/net/net_aix_nocgo.go
index f63a21e..834534d 100644
--- a/vendor/github.com/shirou/gopsutil/v4/net/net_aix_nocgo.go
+++ b/vendor/github.com/shirou/gopsutil/v4/net/net_aix_nocgo.go
@@ -5,7 +5,7 @@ package net
import (
"context"
- "fmt"
+ "errors"
"strconv"
"strings"
@@ -19,7 +19,7 @@ func parseNetstatI(output string) ([]IOCountersStat, error) {
// Check first line is header
if len(lines) > 0 && strings.Fields(lines[0])[0] != "Name" {
- return nil, fmt.Errorf("not a 'netstat -i' output")
+ return nil, errors.New("not a 'netstat -i' output")
}
for _, line := range lines[1:] {
@@ -88,8 +88,8 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
if err != nil {
return nil, err
}
- if pernic == false {
- return getIOCountersAll(iocounters)
+ if !pernic {
+ return getIOCountersAll(iocounters), nil
}
return iocounters, nil
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net_darwin.go b/vendor/github.com/shirou/gopsutil/v4/net/net_darwin.go
index 86c541e..5814a54 100644
--- a/vendor/github.com/shirou/gopsutil/v4/net/net_darwin.go
+++ b/vendor/github.com/shirou/gopsutil/v4/net/net_darwin.go
@@ -30,14 +30,14 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
if columns[0] == "Name" {
err = errNetstatHeader
- return
+ return //nolint:nakedret //FIXME
}
// try to extract the numeric value from <Link#123>
if subMatch := netstatLinkRegexp.FindStringSubmatch(columns[2]); len(subMatch) == 2 {
numericValue, err = strconv.ParseUint(subMatch[1], 10, 64)
if err != nil {
- return
+ return //nolint:nakedret //FIXME
}
linkIDUint := uint(numericValue)
linkID = &linkIDUint
@@ -51,7 +51,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
}
if numberColumns < 11 || numberColumns > 13 {
err = fmt.Errorf("Line %q do have an invalid number of columns %d", line, numberColumns)
- return
+ return //nolint:nakedret //FIXME
}
parsed := make([]uint64, 0, 7)
@@ -74,7 +74,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
}
if numericValue, err = strconv.ParseUint(target, 10, 64); err != nil {
- return
+ return //nolint:nakedret //FIXME
}
parsed = append(parsed, numericValue)
}
@@ -91,7 +91,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
if len(parsed) == 7 {
stat.Dropout = parsed[6]
}
- return
+ return //nolint:nakedret //FIXME
}
type netstatInterface struct {
@@ -163,7 +163,7 @@ func (mapi mapInterfaceNameUsage) notTruncated() []string {
}
// Deprecated: use process.PidsWithContext instead
-func PidsWithContext(ctx context.Context) ([]int32, error) {
+func PidsWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
@@ -249,23 +249,23 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
}
if !pernic {
- return getIOCountersAll(ret)
+ return getIOCountersAll(ret), nil
}
return ret, nil
}
-func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
+func IOCountersByFileWithContext(ctx context.Context, pernic bool, _ string) ([]IOCountersStat, error) {
return IOCountersWithContext(ctx, pernic)
}
-func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
+func FilterCountersWithContext(_ context.Context) ([]FilterStat, error) {
return nil, common.ErrNotImplementedError
}
-func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
+func ConntrackStatsWithContext(_ context.Context, _ bool) ([]ConntrackStat, error) {
return nil, common.ErrNotImplementedError
}
-func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
+func ProtoCountersWithContext(_ context.Context, _ []string) ([]ProtoCountersStat, error) {
return nil, common.ErrNotImplementedError
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net_fallback.go b/vendor/github.com/shirou/gopsutil/v4/net/net_fallback.go
index 7d7596a..29c2a14 100644
--- a/vendor/github.com/shirou/gopsutil/v4/net/net_fallback.go
+++ b/vendor/github.com/shirou/gopsutil/v4/net/net_fallback.go
@@ -9,32 +9,32 @@ import (
"github.com/shirou/gopsutil/v4/internal/common"
)
-func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) {
+func IOCountersWithContext(_ context.Context, _ bool) ([]IOCountersStat, error) {
return []IOCountersStat{}, common.ErrNotImplementedError
}
-func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
+func IOCountersByFileWithContext(ctx context.Context, pernic bool, _ string) ([]IOCountersStat, error) {
return IOCountersWithContext(ctx, pernic)
}
-func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
+func FilterCountersWithContext(_ context.Context) ([]FilterStat, error) {
return nil, common.ErrNotImplementedError
}
-func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
+func ConntrackStatsWithContext(_ context.Context, _ bool) ([]ConntrackStat, error) {
return nil, common.ErrNotImplementedError
}
-func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
+func ProtoCountersWithContext(_ context.Context, _ []string) ([]ProtoCountersStat, error) {
return nil, common.ErrNotImplementedError
}
// Deprecated: use process.PidsWithContext instead
-func PidsWithContext(ctx context.Context) ([]int32, error) {
+func PidsWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
-func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
+func ConnectionsWithContext(_ context.Context, _ string) ([]ConnectionStat, error) {
return []ConnectionStat{}, common.ErrNotImplementedError
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net_freebsd.go b/vendor/github.com/shirou/gopsutil/v4/net/net_freebsd.go
index 655e133..a72aa00 100644
--- a/vendor/github.com/shirou/gopsutil/v4/net/net_freebsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/net/net_freebsd.go
@@ -12,7 +12,7 @@ import (
)
// Deprecated: use process.PidsWithContext instead
-func PidsWithContext(ctx context.Context) ([]int32, error) {
+func PidsWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
@@ -85,24 +85,24 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
}
if !pernic {
- return getIOCountersAll(ret)
+ return getIOCountersAll(ret), nil
}
return ret, nil
}
-func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
+func IOCountersByFileWithContext(ctx context.Context, pernic bool, _ string) ([]IOCountersStat, error) {
return IOCountersWithContext(ctx, pernic)
}
-func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
+func FilterCountersWithContext(_ context.Context) ([]FilterStat, error) {
return nil, common.ErrNotImplementedError
}
-func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
+func ConntrackStatsWithContext(_ context.Context, _ bool) ([]ConntrackStat, error) {
return nil, common.ErrNotImplementedError
}
-func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
+func ProtoCountersWithContext(_ context.Context, _ []string) ([]ProtoCountersStat, error) {
return nil, common.ErrNotImplementedError
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net_linux.go b/vendor/github.com/shirou/gopsutil/v4/net/net_linux.go
index 23113fe..9697526 100644
--- a/vendor/github.com/shirou/gopsutil/v4/net/net_linux.go
+++ b/vendor/github.com/shirou/gopsutil/v4/net/net_linux.go
@@ -27,16 +27,16 @@ const ( // Conntrack Column numbers
ctINVALID
ctIGNORE
ctDELETE
- ctDELETE_LIST
+ ctDELETE_LIST //nolint:revive //FIXME
ctINSERT
- ctINSERT_FAILED
+ ctINSERT_FAILED //nolint:revive //FIXME
ctDROP
- ctEARLY_DROP
- ctICMP_ERROR
- CT_EXPEctNEW
- ctEXPECT_CREATE
- CT_EXPEctDELETE
- ctSEARCH_RESTART
+ ctEARLY_DROP //nolint:revive //FIXME
+ ctICMP_ERROR //nolint:revive //FIXME
+ CT_EXPEctNEW //nolint:revive //FIXME
+ ctEXPECT_CREATE //nolint:revive //FIXME
+ CT_EXPEctDELETE //nolint:revive //FIXME
+ ctSEARCH_RESTART //nolint:revive //FIXME
)
func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) {
@@ -44,7 +44,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
return IOCountersByFileWithContext(ctx, pernic, filename)
}
-func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
+func IOCountersByFileWithContext(_ context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
lines, err := common.ReadLines(filename)
if err != nil {
return nil, err
@@ -128,7 +128,7 @@ func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename stri
}
if !pernic {
- return getIOCountersAll(ret)
+ return getIOCountersAll(ret), nil
}
return ret, nil
@@ -571,8 +571,7 @@ func (p *process) fillFromStatus(ctx context.Context) error {
continue
}
value := tabParts[1]
- switch strings.TrimRight(tabParts[0], ":") {
- case "Uid":
+ if strings.TrimRight(tabParts[0], ":") == "Uid" {
p.uids = make([]int32, 0, 4)
for _, i := range strings.Split(value, "\t") {
v, err := strconv.ParseInt(i, 10, 32)
diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net_openbsd.go b/vendor/github.com/shirou/gopsutil/v4/net/net_openbsd.go
index a90d590..41f0f46 100644
--- a/vendor/github.com/shirou/gopsutil/v4/net/net_openbsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/net/net_openbsd.go
@@ -107,7 +107,7 @@ func ParseNetstat(output string, mode string,
}
// Deprecated: use process.PidsWithContext instead
-func PidsWithContext(ctx context.Context) ([]int32, error) {
+func PidsWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
@@ -150,26 +150,26 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
ret = append(ret, ioc)
}
- if pernic == false {
- return getIOCountersAll(ret)
+ if !pernic {
+ return getIOCountersAll(ret), nil
}
return ret, nil
}
-func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
- return IOCounters(pernic)
+func IOCountersByFileWithContext(ctx context.Context, pernic bool, _ string) ([]IOCountersStat, error) {
+ return IOCountersWithContext(ctx, pernic)
}
-func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
+func FilterCountersWithContext(_ context.Context) ([]FilterStat, error) {
return nil, common.ErrNotImplementedError
}
-func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
+func ConntrackStatsWithContext(_ context.Context, _ bool) ([]ConntrackStat, error) {
return nil, common.ErrNotImplementedError
}
-func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
+func ProtoCountersWithContext(_ context.Context, _ []string) ([]ProtoCountersStat, error) {
return nil, common.ErrNotImplementedError
}
@@ -310,15 +310,15 @@ func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat,
return ret, nil
}
-func ConnectionsPidWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
+func ConnectionsPidWithContext(_ context.Context, _ string, _ int32) ([]ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
-func ConnectionsMaxWithContext(ctx context.Context, kind string, maxConn int) ([]ConnectionStat, error) {
+func ConnectionsMaxWithContext(_ context.Context, _ string, _ int) ([]ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
-func ConnectionsPidMaxWithContext(ctx context.Context, kind string, pid int32, maxConn int) ([]ConnectionStat, error) {
+func ConnectionsPidMaxWithContext(_ context.Context, _ string, _ int32, _ int) ([]ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
@@ -338,6 +338,6 @@ func ConnectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, p
return connectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, maxConn)
}
-func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, maxConn int) ([]ConnectionStat, error) {
+func connectionsPidMaxWithoutUidsWithContext(_ context.Context, _ string, _ int32, _ int) ([]ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net_solaris.go b/vendor/github.com/shirou/gopsutil/v4/net/net_solaris.go
index 83eb1d0..df06780 100644
--- a/vendor/github.com/shirou/gopsutil/v4/net/net_solaris.go
+++ b/vendor/github.com/shirou/gopsutil/v4/net/net_solaris.go
@@ -5,6 +5,7 @@ package net
import (
"context"
+ "errors"
"fmt"
"regexp"
"runtime"
@@ -29,7 +30,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
lines := strings.Split(strings.TrimSpace(string(kstatSysOut)), "\n")
if len(lines) == 0 {
- return nil, fmt.Errorf("no interface found")
+ return nil, errors.New("no interface found")
}
rbytes64arr := make(map[string]uint64)
ipackets64arr := make(map[string]uint64)
@@ -104,34 +105,34 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
}
if !pernic {
- return getIOCountersAll(ret)
+ return getIOCountersAll(ret), nil
}
return ret, nil
}
-func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
+func IOCountersByFileWithContext(ctx context.Context, pernic bool, _ string) ([]IOCountersStat, error) {
return IOCountersWithContext(ctx, pernic)
}
-func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
+func FilterCountersWithContext(_ context.Context) ([]FilterStat, error) {
return nil, common.ErrNotImplementedError
}
-func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
+func ConntrackStatsWithContext(_ context.Context, _ bool) ([]ConntrackStat, error) {
return nil, common.ErrNotImplementedError
}
-func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
+func ProtoCountersWithContext(_ context.Context, _ []string) ([]ProtoCountersStat, error) {
return nil, common.ErrNotImplementedError
}
// Deprecated: use process.PidsWithContext instead
-func PidsWithContext(ctx context.Context) ([]int32, error) {
+func PidsWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
-func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
+func ConnectionsWithContext(_ context.Context, _ string) ([]ConnectionStat, error) {
return []ConnectionStat{}, common.ErrNotImplementedError
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net_unix.go b/vendor/github.com/shirou/gopsutil/v4/net/net_unix.go
index 6eb7e2f..ae7e9d8 100644
--- a/vendor/github.com/shirou/gopsutil/v4/net/net_unix.go
+++ b/vendor/github.com/shirou/gopsutil/v4/net/net_unix.go
@@ -18,7 +18,7 @@ func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat,
return ConnectionsPidWithContext(ctx, kind, 0)
}
-func ConnectionsMaxWithContext(ctx context.Context, kind string, maxConn int) ([]ConnectionStat, error) {
+func ConnectionsMaxWithContext(_ context.Context, _ string, _ int) ([]ConnectionStat, error) {
return []ConnectionStat{}, common.ErrNotImplementedError
}
@@ -163,7 +163,7 @@ func parseNetAddr(line string) (laddr Addr, raddr Addr, err error) {
return laddr, raddr, err
}
-func ConnectionsPidMaxWithContext(ctx context.Context, kind string, pid int32, maxConn int) ([]ConnectionStat, error) {
+func ConnectionsPidMaxWithContext(_ context.Context, _ string, _ int32, _ int) ([]ConnectionStat, error) {
return []ConnectionStat{}, common.ErrNotImplementedError
}
@@ -183,6 +183,6 @@ func ConnectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, p
return connectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, maxConn)
}
-func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, maxConn int) ([]ConnectionStat, error) {
+func connectionsPidMaxWithoutUidsWithContext(_ context.Context, _ string, _ int32, _ int) ([]ConnectionStat, error) {
return []ConnectionStat{}, common.ErrNotImplementedError
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net_windows.go b/vendor/github.com/shirou/gopsutil/v4/net/net_windows.go
index 00ebf89..9622896 100644
--- a/vendor/github.com/shirou/gopsutil/v4/net/net_windows.go
+++ b/vendor/github.com/shirou/gopsutil/v4/net/net_windows.go
@@ -5,14 +5,16 @@ package net
import (
"context"
+ "errors"
"fmt"
"net"
"os"
"syscall"
"unsafe"
- "github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows"
+
+ "github.com/shirou/gopsutil/v4/internal/common"
)
var (
@@ -94,7 +96,7 @@ const (
type mibIfRow2 struct {
InterfaceLuid uint64
InterfaceIndex uint32
- InterfaceGuid guid
+ InterfaceGuid guid //nolint:revive //FIXME
Alias [maxStringSize + 1]uint16
Description [maxStringSize + 1]uint16
PhysicalAddressLength uint32
@@ -111,7 +113,7 @@ type mibIfRow2 struct {
OperStatus uint32
AdminStatus uint32
MediaConnectState uint32
- NetworkGuid guid
+ NetworkGuid guid //nolint:revive //FIXME
ConnectionType uint32
padding1 [pad0for64_4for32]byte
TransmitLinkSpeed uint64
@@ -136,7 +138,7 @@ type mibIfRow2 struct {
OutQLen uint64
}
-func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) {
+func IOCountersWithContext(_ context.Context, pernic bool) ([]IOCountersStat, error) {
ifs, err := net.Interfaces()
if err != nil {
return nil, err
@@ -191,20 +193,20 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
}
if !pernic {
- return getIOCountersAll(counters)
+ return getIOCountersAll(counters), nil
}
return counters, nil
}
-func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
- return IOCounters(pernic)
+func IOCountersByFileWithContext(ctx context.Context, pernic bool, _ string) ([]IOCountersStat, error) {
+ return IOCountersWithContext(ctx, pernic)
}
func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
return ConnectionsPidWithContext(ctx, kind, 0)
}
-func ConnectionsPidWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
+func ConnectionsPidWithContext(_ context.Context, kind string, pid int32) ([]ConnectionStat, error) {
tmap, ok := netConnectionKindMap[kind]
if !ok {
return nil, fmt.Errorf("invalid kind, %s", kind)
@@ -238,7 +240,7 @@ func getProcInet(kinds []netConnectionKindType, pid int32) ([]ConnectionStat, er
func getNetStatWithKind(kindType netConnectionKindType) ([]ConnectionStat, error) {
if kindType.filename == "" {
- return nil, fmt.Errorf("kind filename must be required")
+ return nil, errors.New("kind filename must be required")
}
switch kindType.filename {
@@ -256,7 +258,7 @@ func getNetStatWithKind(kindType netConnectionKindType) ([]ConnectionStat, error
}
// Deprecated: use process.PidsWithContext instead
-func PidsWithContext(ctx context.Context) ([]int32, error) {
+func PidsWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
@@ -288,15 +290,15 @@ func connectionsPidMaxWithoutUidsWithContext(_ context.Context, _ string, _ int3
return []ConnectionStat{}, common.ErrNotImplementedError
}
-func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
+func FilterCountersWithContext(_ context.Context) ([]FilterStat, error) {
return nil, common.ErrNotImplementedError
}
-func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
+func ConntrackStatsWithContext(_ context.Context, _ bool) ([]ConntrackStat, error) {
return nil, common.ErrNotImplementedError
}
-func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
+func ProtoCountersWithContext(_ context.Context, _ []string) ([]ProtoCountersStat, error) {
return nil, common.ErrNotImplementedError
}
@@ -326,7 +328,7 @@ func getTableUintptr(family uint32, buf []byte) uintptr {
return p
}
-func getTableInfo(filename string, table interface{}) (index, step, length int) {
+func getTableInfo(filename string, table any) (index, step, length int) {
switch filename {
case kindTCP4.filename:
index = int(unsafe.Sizeof(table.(pmibTCPTableOwnerPidAll).DwNumEntries))
@@ -360,7 +362,7 @@ func getTCPConnections(family uint32) ([]ConnectionStat, error) {
)
if family == 0 {
- return nil, fmt.Errorf("faimly must be required")
+ return nil, errors.New("faimly must be required")
}
for {
@@ -381,7 +383,7 @@ func getTCPConnections(family uint32) ([]ConnectionStat, error) {
}
}
- err := getExtendedTcpTable(p,
+ err := getExtendedTCPTable(p,
&size,
true,
family,
@@ -390,7 +392,7 @@ func getTCPConnections(family uint32) ([]ConnectionStat, error) {
if err == nil {
break
}
- if err != windows.ERROR_INSUFFICIENT_BUFFER {
+ if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, err
}
buf = make([]byte, size)
@@ -441,7 +443,7 @@ func getUDPConnections(family uint32) ([]ConnectionStat, error) {
)
if family == 0 {
- return nil, fmt.Errorf("faimly must be required")
+ return nil, errors.New("faimly must be required")
}
for {
@@ -462,7 +464,7 @@ func getUDPConnections(family uint32) ([]ConnectionStat, error) {
}
}
- err := getExtendedUdpTable(
+ err := getExtendedUDPTable(
p,
&size,
true,
@@ -473,7 +475,7 @@ func getUDPConnections(family uint32) ([]ConnectionStat, error) {
if err == nil {
break
}
- if err != windows.ERROR_INSUFFICIENT_BUFFER {
+ if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, err
}
buf = make([]byte, size)
@@ -526,16 +528,16 @@ var tcpStatuses = map[mibTCPState]string{
12: "DELETE",
}
-func getExtendedTcpTable(pTcpTable uintptr, pdwSize *uint32, bOrder bool, ulAf uint32, tableClass tcpTableClass, reserved uint32) (errcode error) {
- r1, _, _ := syscall.Syscall6(procGetExtendedTCPTable.Addr(), 6, pTcpTable, uintptr(unsafe.Pointer(pdwSize)), getUintptrFromBool(bOrder), uintptr(ulAf), uintptr(tableClass), uintptr(reserved))
+func getExtendedTCPTable(pTCPTable uintptr, pdwSize *uint32, bOrder bool, ulAf uint32, tableClass tcpTableClass, reserved uint32) (errcode error) {
+ r1, _, _ := syscall.Syscall6(procGetExtendedTCPTable.Addr(), 6, pTCPTable, uintptr(unsafe.Pointer(pdwSize)), getUintptrFromBool(bOrder), uintptr(ulAf), uintptr(tableClass), uintptr(reserved))
if r1 != 0 {
errcode = syscall.Errno(r1)
}
return
}
-func getExtendedUdpTable(pUdpTable uintptr, pdwSize *uint32, bOrder bool, ulAf uint32, tableClass udpTableClass, reserved uint32) (errcode error) {
- r1, _, _ := syscall.Syscall6(procGetExtendedUDPTable.Addr(), 6, pUdpTable, uintptr(unsafe.Pointer(pdwSize)), getUintptrFromBool(bOrder), uintptr(ulAf), uintptr(tableClass), uintptr(reserved))
+func getExtendedUDPTable(pUDPTable uintptr, pdwSize *uint32, bOrder bool, ulAf uint32, tableClass udpTableClass, reserved uint32) (errcode error) {
+ r1, _, _ := syscall.Syscall6(procGetExtendedUDPTable.Addr(), 6, pUDPTable, uintptr(unsafe.Pointer(pdwSize)), getUintptrFromBool(bOrder), uintptr(ulAf), uintptr(tableClass), uintptr(reserved))
if r1 != 0 {
errcode = syscall.Errno(r1)
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process.go b/vendor/github.com/shirou/gopsutil/v4/process/process.go
index 70411c6..0bd4d9e 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process.go
@@ -269,13 +269,11 @@ func (p *Process) PercentWithContext(ctx context.Context, interval time.Duration
if err != nil {
return 0, err
}
- } else {
- if p.lastCPUTimes == nil {
- // invoked first time
- p.lastCPUTimes = cpuTimes
- p.lastCPUTime = now
- return 0, nil
- }
+ } else if p.lastCPUTimes == nil {
+ // invoked first time
+ p.lastCPUTimes = cpuTimes
+ p.lastCPUTime = now
+ return 0, nil
}
numcpu := runtime.NumCPU()
@@ -326,12 +324,12 @@ func calculatePercent(t1, t2 *cpu.TimesStat, delta float64, numcpu int) float64
return 0
}
// https://github.com/giampaolo/psutil/blob/c034e6692cf736b5e87d14418a8153bb03f6cf42/psutil/__init__.py#L1064
- delta_proc := (t2.User - t1.User) + (t2.System - t1.System)
- if delta_proc <= 0 {
+ deltaProc := (t2.User - t1.User) + (t2.System - t1.System)
+ if deltaProc <= 0 {
return 0
}
- overall_percent := ((delta_proc / delta) * 100) * float64(numcpu)
- return overall_percent
+ overallPercent := ((deltaProc / delta) * 100) * float64(numcpu)
+ return overallPercent
}
// MemoryPercent returns how many percent of the total RAM this process uses
@@ -361,7 +359,7 @@ func (p *Process) CPUPercent() (float64, error) {
}
func (p *Process) CPUPercentWithContext(ctx context.Context) (float64, error) {
- crt_time, err := p.createTimeWithContext(ctx)
+ createTime, err := p.createTimeWithContext(ctx)
if err != nil {
return 0, err
}
@@ -371,7 +369,7 @@ func (p *Process) CPUPercentWithContext(ctx context.Context) (float64, error) {
return 0, err
}
- created := time.Unix(0, crt_time*int64(time.Millisecond))
+ created := time.Unix(0, createTime*int64(time.Millisecond))
totalTime := time.Since(created).Seconds()
if totalTime <= 0 {
return 0, nil
@@ -408,6 +406,11 @@ func (p *Process) Cmdline() (string, error) {
// CmdlineSlice returns the command line arguments of the process as a slice with each
// element being an argument.
+//
+// On Windows, this assumes the command line is encoded according to the convention accepted by
+// [golang.org/x/sys/windows.CmdlineToArgv] (the most common convention). If this is not suitable,
+// you should instead use [Process.Cmdline] and parse the command line according to your specific
+// requirements.
func (p *Process) CmdlineSlice() ([]string, error) {
return p.CmdlineSliceWithContext(context.Background())
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_bsd.go b/vendor/github.com/shirou/gopsutil/v4/process/process_bsd.go
index dcc0561..1a58c3e 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_bsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_bsd.go
@@ -16,55 +16,55 @@ type MemoryInfoExStat struct{}
type MemoryMapsStat struct{}
-func (p *Process) TgidWithContext(ctx context.Context) (int32, error) {
+func (p *Process) TgidWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) {
+func (p *Process) IOniceWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
+func (p *Process) RlimitWithContext(_ context.Context) ([]RlimitStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
+func (p *Process) RlimitUsageWithContext(_ context.Context, _ bool) ([]RlimitStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
+func (p *Process) NumCtxSwitchesWithContext(_ context.Context) (*NumCtxSwitchesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NumFDsWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
+func (p *Process) CPUAffinityWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
+func (p *Process) MemoryInfoExWithContext(_ context.Context) (*MemoryInfoExStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
+func (p *Process) PageFaultsWithContext(_ context.Context) (*PageFaultsStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) {
+func (p *Process) OpenFilesWithContext(_ context.Context) ([]OpenFilesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
+func (p *Process) MemoryMapsWithContext(_ context.Context, _ bool) (*[]MemoryMapsStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
+func (p *Process) ThreadsWithContext(_ context.Context) (map[int32]*cpu.TimesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) {
+func (p *Process) EnvironWithContext(_ context.Context) ([]string, error) {
return nil, common.ErrNotImplementedError
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_darwin.go b/vendor/github.com/shirou/gopsutil/v4/process/process_darwin.go
index 33abc10..5afafd8 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_darwin.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_darwin.go
@@ -7,6 +7,7 @@ import (
"bytes"
"context"
"encoding/binary"
+ "errors"
"fmt"
"path/filepath"
"runtime"
@@ -32,11 +33,11 @@ const (
KernProcPathname = 12 // path to executable
)
-type _Ctype_struct___0 struct {
+type _Ctype_struct___0 struct { //nolint:revive //FIXME
Pad uint64
}
-func pidsWithContext(ctx context.Context) ([]int32, error) {
+func pidsWithContext(_ context.Context) ([]int32, error) {
var ret []int32
kprocs, err := unix.SysctlKinfoProcSlice("kern.proc.all")
@@ -51,7 +52,7 @@ func pidsWithContext(ctx context.Context) ([]int32, error) {
return ret, nil
}
-func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
+func (p *Process) PpidWithContext(_ context.Context) (int32, error) {
k, err := p.getKProc()
if err != nil {
return 0, err
@@ -84,7 +85,7 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
return name, nil
}
-func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
+func (p *Process) createTimeWithContext(_ context.Context) (int64, error) {
k, err := p.getKProc()
if err != nil {
return 0, err
@@ -112,7 +113,7 @@ func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
return strings.IndexByte(string(out), '+') != -1, nil
}
-func (p *Process) UidsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) UidsWithContext(_ context.Context) ([]uint32, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
@@ -124,7 +125,7 @@ func (p *Process) UidsWithContext(ctx context.Context) ([]uint32, error) {
return []uint32{userEffectiveUID}, nil
}
-func (p *Process) GidsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) GidsWithContext(_ context.Context) ([]uint32, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
@@ -136,7 +137,7 @@ func (p *Process) GidsWithContext(ctx context.Context) ([]uint32, error) {
return gids, nil
}
-func (p *Process) GroupsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) GroupsWithContext(_ context.Context) ([]uint32, error) {
return nil, common.ErrNotImplementedError
// k, err := p.getKProc()
// if err != nil {
@@ -151,7 +152,7 @@ func (p *Process) GroupsWithContext(ctx context.Context) ([]uint32, error) {
// return groups, nil
}
-func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
+func (p *Process) TerminalWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
/*
k, err := p.getKProc()
@@ -169,7 +170,7 @@ func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
*/
}
-func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NiceWithContext(_ context.Context) (int32, error) {
k, err := p.getKProc()
if err != nil {
return 0, err
@@ -177,7 +178,7 @@ func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
return int32(k.Proc.P_nice), nil
}
-func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
+func (p *Process) IOCountersWithContext(_ context.Context) (*IOCountersStat, error) {
return nil, common.ErrNotImplementedError
}
@@ -239,11 +240,12 @@ func (p *Process) getKProc() (*unix.KinfoProc, error) {
// If passed arg pid is 0, get information from all process.
func callPsWithContext(ctx context.Context, arg string, pid int32, threadOption bool, nameOption bool) ([][]string, error) {
var cmd []string
- if pid == 0 { // will get from all processes.
+ switch {
+ case pid == 0: // will get from all processes.
cmd = []string{"-ax", "-o", arg}
- } else if threadOption {
+ case threadOption:
cmd = []string{"-x", "-o", arg, "-M", "-p", strconv.Itoa(int(pid))}
- } else {
+ default:
cmd = []string{"-x", "-o", arg, "-p", strconv.Itoa(int(pid))}
}
if nameOption {
@@ -303,7 +305,7 @@ func getTimeScaleToNanoSeconds() float64 {
return float64(timeBaseInfo.Numer) / float64(timeBaseInfo.Denom)
}
-func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
+func (p *Process) ExeWithContext(_ context.Context) (string, error) {
lib, err := registerFuncs()
if err != nil {
return "", err
@@ -332,7 +334,7 @@ type vnodePathInfo struct {
// EUID can access. Otherwise "operation not permitted" will be returned as the
// error.
// Note: This might also work for other *BSD OSs.
-func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
+func (p *Process) CwdWithContext(_ context.Context) (string, error) {
lib, err := registerFuncs()
if err != nil {
return "", err
@@ -348,7 +350,7 @@ func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
ret := procPidInfo(p.Pid, common.PROC_PIDVNODEPATHINFO, 0, uintptr(unsafe.Pointer(&vpi)), vpiSize)
errno, _ := lib.Dlsym("errno")
err = *(**unix.Errno)(unsafe.Pointer(&errno))
- if err == unix.EPERM {
+ if errors.Is(err, unix.EPERM) {
return "", ErrorNotPermitted
}
@@ -373,11 +375,11 @@ func procArgs(pid int32) ([]byte, int, error) {
return procargs, int(binary.LittleEndian.Uint32(nargs)), nil
}
-func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
- return p.cmdlineSliceWithContext(ctx, true)
+func (p *Process) CmdlineSliceWithContext(_ context.Context) ([]string, error) {
+ return p.cmdlineSlice()
}
-func (p *Process) cmdlineSliceWithContext(ctx context.Context, fallback bool) ([]string, error) {
+func (p *Process) cmdlineSlice() ([]string, error) {
pargs, nargs, err := procArgs(p.Pid)
if err != nil {
return nil, err
@@ -393,7 +395,7 @@ func (p *Process) cmdlineSliceWithContext(ctx context.Context, fallback bool) ([
// are the arguments. Everything else in the slice is then the environment
// of the process.
for _, arg := range args[1:] {
- argStr = string(arg[:])
+ argStr = string(arg)
if len(argStr) > 0 {
if nargs > 0 {
argSlice = append(argSlice, argStr)
@@ -408,8 +410,8 @@ func (p *Process) cmdlineSliceWithContext(ctx context.Context, fallback bool) ([
}
// cmdNameWithContext returns the command name (including spaces) without any arguments
-func (p *Process) cmdNameWithContext(ctx context.Context) (string, error) {
- r, err := p.cmdlineSliceWithContext(ctx, false)
+func (p *Process) cmdNameWithContext(_ context.Context) (string, error) {
+ r, err := p.cmdlineSlice()
if err != nil {
return "", err
}
@@ -429,7 +431,7 @@ func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
return strings.Join(r, " "), err
}
-func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NumThreadsWithContext(_ context.Context) (int32, error) {
lib, err := registerFuncs()
if err != nil {
return 0, err
@@ -442,7 +444,7 @@ func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
return int32(ti.Threadnum), nil
}
-func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
+func (p *Process) TimesWithContext(_ context.Context) (*cpu.TimesStat, error) {
lib, err := registerFuncs()
if err != nil {
return nil, err
@@ -461,7 +463,7 @@ func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error)
return ret, nil
}
-func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
+func (p *Process) MemoryInfoWithContext(_ context.Context) (*MemoryInfoStat, error) {
lib, err := registerFuncs()
if err != nil {
return nil, err
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_fallback.go b/vendor/github.com/shirou/gopsutil/v4/process/process_fallback.go
index e5410ea..b014297 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_fallback.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_fallback.go
@@ -30,174 +30,174 @@ type MemoryMapsStat struct {
type MemoryInfoExStat struct{}
-func pidsWithContext(ctx context.Context) ([]int32, error) {
+func pidsWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
-func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
+func ProcessesWithContext(_ context.Context) ([]*Process, error) {
return nil, common.ErrNotImplementedError
}
-func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
+func PidExistsWithContext(_ context.Context, _ int32) (bool, error) {
return false, common.ErrNotImplementedError
}
-func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
+func (p *Process) PpidWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) NameWithContext(ctx context.Context) (string, error) {
+func (p *Process) NameWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) TgidWithContext(ctx context.Context) (int32, error) {
+func (p *Process) TgidWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
+func (p *Process) ExeWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
+func (p *Process) CmdlineWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
+func (p *Process) CmdlineSliceWithContext(_ context.Context) ([]string, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
+func (p *Process) createTimeWithContext(_ context.Context) (int64, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
+func (p *Process) CwdWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
+func (p *Process) StatusWithContext(_ context.Context) ([]string, error) {
return []string{""}, common.ErrNotImplementedError
}
-func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
+func (p *Process) ForegroundWithContext(_ context.Context) (bool, error) {
return false, common.ErrNotImplementedError
}
-func (p *Process) UidsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) UidsWithContext(_ context.Context) ([]uint32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) GidsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) GidsWithContext(_ context.Context) ([]uint32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) GroupsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) GroupsWithContext(_ context.Context) ([]uint32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
+func (p *Process) TerminalWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NiceWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) {
+func (p *Process) IOniceWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
+func (p *Process) RlimitWithContext(_ context.Context) ([]RlimitStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
+func (p *Process) RlimitUsageWithContext(_ context.Context, _ bool) ([]RlimitStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
+func (p *Process) IOCountersWithContext(_ context.Context) (*IOCountersStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
+func (p *Process) NumCtxSwitchesWithContext(_ context.Context) (*NumCtxSwitchesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NumFDsWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NumThreadsWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
+func (p *Process) ThreadsWithContext(_ context.Context) (map[int32]*cpu.TimesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
+func (p *Process) TimesWithContext(_ context.Context) (*cpu.TimesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
+func (p *Process) CPUAffinityWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
+func (p *Process) MemoryInfoWithContext(_ context.Context) (*MemoryInfoStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
+func (p *Process) MemoryInfoExWithContext(_ context.Context) (*MemoryInfoExStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
+func (p *Process) PageFaultsWithContext(_ context.Context) (*PageFaultsStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
+func (p *Process) ChildrenWithContext(_ context.Context) ([]*Process, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) {
+func (p *Process) OpenFilesWithContext(_ context.Context) ([]OpenFilesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
+func (p *Process) ConnectionsWithContext(_ context.Context) ([]net.ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) ConnectionsMaxWithContext(ctx context.Context, maxConn int) ([]net.ConnectionStat, error) {
+func (p *Process) ConnectionsMaxWithContext(_ context.Context, _ int) ([]net.ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
+func (p *Process) MemoryMapsWithContext(_ context.Context, _ bool) (*[]MemoryMapsStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) SendSignalWithContext(ctx context.Context, sig Signal) error {
+func (p *Process) SendSignalWithContext(_ context.Context, _ Signal) error {
return common.ErrNotImplementedError
}
-func (p *Process) SuspendWithContext(ctx context.Context) error {
+func (p *Process) SuspendWithContext(_ context.Context) error {
return common.ErrNotImplementedError
}
-func (p *Process) ResumeWithContext(ctx context.Context) error {
+func (p *Process) ResumeWithContext(_ context.Context) error {
return common.ErrNotImplementedError
}
-func (p *Process) TerminateWithContext(ctx context.Context) error {
+func (p *Process) TerminateWithContext(_ context.Context) error {
return common.ErrNotImplementedError
}
-func (p *Process) KillWithContext(ctx context.Context) error {
+func (p *Process) KillWithContext(_ context.Context) error {
return common.ErrNotImplementedError
}
-func (p *Process) UsernameWithContext(ctx context.Context) (string, error) {
+func (p *Process) UsernameWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) {
+func (p *Process) EnvironWithContext(_ context.Context) ([]string, error) {
return nil, common.ErrNotImplementedError
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_freebsd.go b/vendor/github.com/shirou/gopsutil/v4/process/process_freebsd.go
index a67ac0e..6df3142 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_freebsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_freebsd.go
@@ -34,7 +34,7 @@ func pidsWithContext(ctx context.Context) ([]int32, error) {
return ret, nil
}
-func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
+func (p *Process) PpidWithContext(_ context.Context) (int32, error) {
k, err := p.getKProc()
if err != nil {
return 0, err
@@ -66,7 +66,7 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
return name, nil
}
-func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
+func (p *Process) CwdWithContext(_ context.Context) (string, error) {
mib := []int32{CTLKern, KernProc, KernProcCwd, p.Pid}
buf, length, err := common.CallSyscall(mib)
if err != nil {
@@ -87,7 +87,7 @@ func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
return cwd, nil
}
-func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
+func (p *Process) ExeWithContext(_ context.Context) (string, error) {
mib := []int32{CTLKern, KernProc, KernProcPathname, p.Pid}
buf, _, err := common.CallSyscall(mib)
if err != nil {
@@ -97,7 +97,7 @@ func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
return strings.Trim(string(buf), "\x00"), nil
}
-func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
+func (p *Process) CmdlineWithContext(_ context.Context) (string, error) {
mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid}
buf, _, err := common.CallSyscall(mib)
if err != nil {
@@ -110,7 +110,7 @@ func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
return strings.Join(ret, " "), nil
}
-func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
+func (p *Process) CmdlineSliceWithContext(_ context.Context) ([]string, error) {
mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid}
buf, _, err := common.CallSyscall(mib)
if err != nil {
@@ -131,7 +131,7 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error)
return strParts, nil
}
-func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
+func (p *Process) createTimeWithContext(_ context.Context) (int64, error) {
k, err := p.getKProc()
if err != nil {
return 0, err
@@ -139,7 +139,7 @@ func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
return int64(k.Start.Sec)*1000 + int64(k.Start.Usec)/1000, nil
}
-func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
+func (p *Process) StatusWithContext(_ context.Context) ([]string, error) {
k, err := p.getKProc()
if err != nil {
return []string{""}, err
@@ -175,7 +175,7 @@ func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
return strings.IndexByte(string(out), '+') != -1, nil
}
-func (p *Process) UidsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) UidsWithContext(_ context.Context) ([]uint32, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
@@ -188,7 +188,7 @@ func (p *Process) UidsWithContext(ctx context.Context) ([]uint32, error) {
return uids, nil
}
-func (p *Process) GidsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) GidsWithContext(_ context.Context) ([]uint32, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
@@ -200,7 +200,7 @@ func (p *Process) GidsWithContext(ctx context.Context) ([]uint32, error) {
return gids, nil
}
-func (p *Process) GroupsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) GroupsWithContext(_ context.Context) ([]uint32, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
@@ -214,7 +214,7 @@ func (p *Process) GroupsWithContext(ctx context.Context) ([]uint32, error) {
return groups, nil
}
-func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
+func (p *Process) TerminalWithContext(_ context.Context) (string, error) {
k, err := p.getKProc()
if err != nil {
return "", err
@@ -230,7 +230,7 @@ func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
return termmap[ttyNr], nil
}
-func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NiceWithContext(_ context.Context) (int32, error) {
k, err := p.getKProc()
if err != nil {
return 0, err
@@ -238,7 +238,7 @@ func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
return int32(k.Nice), nil
}
-func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
+func (p *Process) IOCountersWithContext(_ context.Context) (*IOCountersStat, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
@@ -249,7 +249,7 @@ func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, e
}, nil
}
-func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NumThreadsWithContext(_ context.Context) (int32, error) {
k, err := p.getKProc()
if err != nil {
return 0, err
@@ -258,7 +258,7 @@ func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
return k.Numthreads, nil
}
-func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
+func (p *Process) TimesWithContext(_ context.Context) (*cpu.TimesStat, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
@@ -270,7 +270,7 @@ func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error)
}, nil
}
-func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
+func (p *Process) MemoryInfoWithContext(_ context.Context) (*MemoryInfoStat, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_linux.go b/vendor/github.com/shirou/gopsutil/v4/process/process_linux.go
index 68a8c88..bf96fd3 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_linux.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_linux.go
@@ -194,7 +194,7 @@ func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
return nice, nil
}
-func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) {
+func (p *Process) IOniceWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
@@ -310,7 +310,7 @@ func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error)
return cpuTimes, nil
}
-func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
+func (p *Process) CPUAffinityWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_openbsd.go b/vendor/github.com/shirou/gopsutil/v4/process/process_openbsd.go
index 5e8a9e0..5a6d361 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_openbsd.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_openbsd.go
@@ -8,7 +8,6 @@ import (
"context"
"encoding/binary"
"errors"
- "fmt"
"io"
"path/filepath"
"sort"
@@ -16,11 +15,12 @@ import (
"strings"
"unsafe"
- cpu "github.com/shirou/gopsutil/v4/cpu"
- "github.com/shirou/gopsutil/v4/internal/common"
- mem "github.com/shirou/gopsutil/v4/mem"
- net "github.com/shirou/gopsutil/v4/net"
"golang.org/x/sys/unix"
+
+ "github.com/shirou/gopsutil/v4/cpu"
+ "github.com/shirou/gopsutil/v4/internal/common"
+ "github.com/shirou/gopsutil/v4/mem"
+ "github.com/shirou/gopsutil/v4/net"
)
func pidsWithContext(ctx context.Context) ([]int32, error) {
@@ -37,7 +37,7 @@ func pidsWithContext(ctx context.Context) ([]int32, error) {
return ret, nil
}
-func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
+func (p *Process) PpidWithContext(_ context.Context) (int32, error) {
k, err := p.getKProc()
if err != nil {
return 0, err
@@ -69,7 +69,7 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
return name, nil
}
-func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
+func (p *Process) CwdWithContext(_ context.Context) (string, error) {
mib := []int32{CTLKern, KernProcCwd, p.Pid}
buf, _, err := common.CallSyscall(mib)
if err != nil {
@@ -78,11 +78,11 @@ func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
return common.ByteToString(buf), nil
}
-func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
+func (p *Process) ExeWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
+func (p *Process) CmdlineSliceWithContext(_ context.Context) ([]string, error) {
mib := []int32{CTLKern, KernProcArgs, p.Pid, KernProcArgv}
buf, _, err := common.CallSyscall(mib)
if err != nil {
@@ -130,7 +130,7 @@ func readPtr(r io.Reader) (uintptr, error) {
}
return uintptr(p), nil
default:
- return 0, fmt.Errorf("unsupported pointer size")
+ return 0, errors.New("unsupported pointer size")
}
}
@@ -142,11 +142,11 @@ func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
return strings.Join(argv, " "), nil
}
-func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
+func (p *Process) createTimeWithContext(_ context.Context) (int64, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
+func (p *Process) StatusWithContext(_ context.Context) ([]string, error) {
k, err := p.getKProc()
if err != nil {
return []string{""}, err
@@ -178,7 +178,7 @@ func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
return strings.IndexByte(string(out), '+') != -1, nil
}
-func (p *Process) UidsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) UidsWithContext(_ context.Context) ([]uint32, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
@@ -191,7 +191,7 @@ func (p *Process) UidsWithContext(ctx context.Context) ([]uint32, error) {
return uids, nil
}
-func (p *Process) GidsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) GidsWithContext(_ context.Context) ([]uint32, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
@@ -203,7 +203,7 @@ func (p *Process) GidsWithContext(ctx context.Context) ([]uint32, error) {
return gids, nil
}
-func (p *Process) GroupsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) GroupsWithContext(_ context.Context) ([]uint32, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
@@ -217,7 +217,7 @@ func (p *Process) GroupsWithContext(ctx context.Context) ([]uint32, error) {
return groups, nil
}
-func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
+func (p *Process) TerminalWithContext(_ context.Context) (string, error) {
k, err := p.getKProc()
if err != nil {
return "", err
@@ -233,7 +233,7 @@ func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
return termmap[ttyNr], nil
}
-func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NiceWithContext(_ context.Context) (int32, error) {
k, err := p.getKProc()
if err != nil {
return 0, err
@@ -241,7 +241,7 @@ func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
return int32(k.Nice), nil
}
-func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
+func (p *Process) IOCountersWithContext(_ context.Context) (*IOCountersStat, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
@@ -252,12 +252,12 @@ func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, e
}, nil
}
-func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NumThreadsWithContext(_ context.Context) (int32, error) {
/* not supported, just return 1 */
return 1, nil
}
-func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
+func (p *Process) TimesWithContext(_ context.Context) (*cpu.TimesStat, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
@@ -305,11 +305,11 @@ func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
return ret, nil
}
-func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
+func (p *Process) ConnectionsWithContext(_ context.Context) ([]net.ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) ConnectionsMaxWithContext(ctx context.Context, maxConn int) ([]net.ConnectionStat, error) {
+func (p *Process) ConnectionsMaxWithContext(_ context.Context, _ int) ([]net.ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_plan9.go b/vendor/github.com/shirou/gopsutil/v4/process/process_plan9.go
index c82e54a..7f68771 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_plan9.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_plan9.go
@@ -30,174 +30,174 @@ type MemoryMapsStat struct {
type MemoryInfoExStat struct{}
-func pidsWithContext(ctx context.Context) ([]int32, error) {
+func pidsWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
-func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
+func ProcessesWithContext(_ context.Context) ([]*Process, error) {
return nil, common.ErrNotImplementedError
}
-func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
+func PidExistsWithContext(_ context.Context, _ int32) (bool, error) {
return false, common.ErrNotImplementedError
}
-func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
+func (p *Process) PpidWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) NameWithContext(ctx context.Context) (string, error) {
+func (p *Process) NameWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) TgidWithContext(ctx context.Context) (int32, error) {
+func (p *Process) TgidWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
+func (p *Process) ExeWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
+func (p *Process) CmdlineWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
+func (p *Process) CmdlineSliceWithContext(_ context.Context) ([]string, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
+func (p *Process) createTimeWithContext(_ context.Context) (int64, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
+func (p *Process) CwdWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
+func (p *Process) StatusWithContext(_ context.Context) ([]string, error) {
return []string{""}, common.ErrNotImplementedError
}
-func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
+func (p *Process) ForegroundWithContext(_ context.Context) (bool, error) {
return false, common.ErrNotImplementedError
}
-func (p *Process) UidsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) UidsWithContext(_ context.Context) ([]uint32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) GidsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) GidsWithContext(_ context.Context) ([]uint32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) GroupsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) GroupsWithContext(_ context.Context) ([]uint32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
+func (p *Process) TerminalWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NiceWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) {
+func (p *Process) IOniceWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
+func (p *Process) RlimitWithContext(_ context.Context) ([]RlimitStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
+func (p *Process) RlimitUsageWithContext(_ context.Context, _ bool) ([]RlimitStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
+func (p *Process) IOCountersWithContext(_ context.Context) (*IOCountersStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
+func (p *Process) NumCtxSwitchesWithContext(_ context.Context) (*NumCtxSwitchesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NumFDsWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NumThreadsWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
+func (p *Process) ThreadsWithContext(_ context.Context) (map[int32]*cpu.TimesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
+func (p *Process) TimesWithContext(_ context.Context) (*cpu.TimesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
+func (p *Process) CPUAffinityWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
+func (p *Process) MemoryInfoWithContext(_ context.Context) (*MemoryInfoStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
+func (p *Process) MemoryInfoExWithContext(_ context.Context) (*MemoryInfoExStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
+func (p *Process) PageFaultsWithContext(_ context.Context) (*PageFaultsStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
+func (p *Process) ChildrenWithContext(_ context.Context) ([]*Process, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) {
+func (p *Process) OpenFilesWithContext(_ context.Context) ([]OpenFilesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
+func (p *Process) ConnectionsWithContext(_ context.Context) ([]net.ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) ConnectionsMaxWithContext(ctx context.Context, maxConn int) ([]net.ConnectionStat, error) {
+func (p *Process) ConnectionsMaxWithContext(_ context.Context, _ int) ([]net.ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
+func (p *Process) MemoryMapsWithContext(_ context.Context, _ bool) (*[]MemoryMapsStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) SendSignalWithContext(ctx context.Context, sig Signal) error {
+func (p *Process) SendSignalWithContext(_ context.Context, _ Signal) error {
return common.ErrNotImplementedError
}
-func (p *Process) SuspendWithContext(ctx context.Context) error {
+func (p *Process) SuspendWithContext(_ context.Context) error {
return common.ErrNotImplementedError
}
-func (p *Process) ResumeWithContext(ctx context.Context) error {
+func (p *Process) ResumeWithContext(_ context.Context) error {
return common.ErrNotImplementedError
}
-func (p *Process) TerminateWithContext(ctx context.Context) error {
+func (p *Process) TerminateWithContext(_ context.Context) error {
return common.ErrNotImplementedError
}
-func (p *Process) KillWithContext(ctx context.Context) error {
+func (p *Process) KillWithContext(_ context.Context) error {
return common.ErrNotImplementedError
}
-func (p *Process) UsernameWithContext(ctx context.Context) (string, error) {
+func (p *Process) UsernameWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) {
+func (p *Process) EnvironWithContext(_ context.Context) ([]string, error) {
return nil, common.ErrNotImplementedError
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_posix.go b/vendor/github.com/shirou/gopsutil/v4/process/process_posix.go
index 96c5e06..12d5fe2 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_posix.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_posix.go
@@ -71,7 +71,7 @@ func getTerminalMap() (map[uint64]string, error) {
return nil, err
}
rdev := uint64(stat.Rdev)
- ret[rdev] = strings.Replace(name, "/dev", "", -1)
+ ret[rdev] = strings.ReplaceAll(name, "/dev", "")
}
return ret, nil
}
@@ -140,7 +140,7 @@ func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
return false, err
}
-func (p *Process) SendSignalWithContext(ctx context.Context, sig syscall.Signal) error {
+func (p *Process) SendSignalWithContext(_ context.Context, sig syscall.Signal) error {
process, err := os.FindProcess(int(p.Pid))
if err != nil {
return err
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_solaris.go b/vendor/github.com/shirou/gopsutil/v4/process/process_solaris.go
index 5c8d4d3..6af5633 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_solaris.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_solaris.go
@@ -52,15 +52,15 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
return out, nil
}
-func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
+func (p *Process) PpidWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) NameWithContext(ctx context.Context) (string, error) {
+func (p *Process) NameWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) TgidWithContext(ctx context.Context) (int32, error) {
+func (p *Process) TgidWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
@@ -80,7 +80,7 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error)
return p.fillSliceFromCmdlineWithContext(ctx)
}
-func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
+func (p *Process) createTimeWithContext(_ context.Context) (int64, error) {
return 0, common.ErrNotImplementedError
}
@@ -88,51 +88,51 @@ func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
return p.fillFromPathCwdWithContext(ctx)
}
-func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
+func (p *Process) StatusWithContext(_ context.Context) ([]string, error) {
return []string{""}, common.ErrNotImplementedError
}
-func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
+func (p *Process) ForegroundWithContext(_ context.Context) (bool, error) {
return false, common.ErrNotImplementedError
}
-func (p *Process) UidsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) UidsWithContext(_ context.Context) ([]uint32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) GidsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) GidsWithContext(_ context.Context) ([]uint32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) GroupsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) GroupsWithContext(_ context.Context) ([]uint32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
+func (p *Process) TerminalWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
-func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NiceWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) {
+func (p *Process) IOniceWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
+func (p *Process) RlimitWithContext(_ context.Context) ([]RlimitStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
+func (p *Process) RlimitUsageWithContext(_ context.Context, _ bool) ([]RlimitStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
+func (p *Process) IOCountersWithContext(_ context.Context) (*IOCountersStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
+func (p *Process) NumCtxSwitchesWithContext(_ context.Context) (*NumCtxSwitchesStat, error) {
return nil, common.ErrNotImplementedError
}
@@ -141,55 +141,55 @@ func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
return int32(len(fnames)), err
}
-func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NumThreadsWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
+func (p *Process) ThreadsWithContext(_ context.Context) (map[int32]*cpu.TimesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
+func (p *Process) TimesWithContext(_ context.Context) (*cpu.TimesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
+func (p *Process) CPUAffinityWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
+func (p *Process) MemoryInfoWithContext(_ context.Context) (*MemoryInfoStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
+func (p *Process) MemoryInfoExWithContext(_ context.Context) (*MemoryInfoExStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
+func (p *Process) PageFaultsWithContext(_ context.Context) (*PageFaultsStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
+func (p *Process) ChildrenWithContext(_ context.Context) ([]*Process, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) {
+func (p *Process) OpenFilesWithContext(_ context.Context) ([]OpenFilesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
+func (p *Process) ConnectionsWithContext(_ context.Context) ([]net.ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) ConnectionsMaxWithContext(ctx context.Context, maxConn int) ([]net.ConnectionStat, error) {
+func (p *Process) ConnectionsMaxWithContext(_ context.Context, _ int) ([]net.ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
+func (p *Process) MemoryMapsWithContext(_ context.Context, _ bool) (*[]MemoryMapsStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) {
+func (p *Process) EnvironWithContext(_ context.Context) ([]string, error) {
return nil, common.ErrNotImplementedError
}
@@ -247,10 +247,7 @@ func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error
return "", err
}
ret := strings.FieldsFunc(string(cmdline), func(r rune) bool {
- if r == '\u0000' {
- return true
- }
- return false
+ return r == '\u0000'
})
return strings.Join(ret, " "), nil
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_windows.go b/vendor/github.com/shirou/gopsutil/v4/process/process_windows.go
index 012886d..c6069a5 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_windows.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_windows.go
@@ -12,16 +12,16 @@ import (
"os"
"path/filepath"
"reflect"
- "strings"
"syscall"
"time"
"unicode/utf16"
"unsafe"
+ "golang.org/x/sys/windows"
+
"github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/internal/common"
"github.com/shirou/gopsutil/v4/net"
- "golang.org/x/sys/windows"
)
type Signal = syscall.Signal
@@ -241,11 +241,11 @@ func init() {
0)
}
-func pidsWithContext(ctx context.Context) ([]int32, error) {
+func pidsWithContext(_ context.Context) ([]int32, error) {
// inspired by https://gist.github.com/henkman/3083408
// and https://github.com/giampaolo/psutil/blob/1c3a15f637521ba5c0031283da39c733fda53e4c/psutil/arch/windows/process_info.c#L315-L329
var ret []int32
- var read uint32 = 0
+ var read uint32
var psSize uint32 = 1024
const dwordSize uint32 = 4
@@ -288,10 +288,10 @@ func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
return false, err
}
h, err := windows.OpenProcess(windows.SYNCHRONIZE, false, uint32(pid))
- if err == windows.ERROR_ACCESS_DENIED {
+ if errors.Is(err, windows.ERROR_ACCESS_DENIED) {
return true, nil
}
- if err == windows.ERROR_INVALID_PARAMETER {
+ if errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
return false, nil
}
if err != nil {
@@ -302,7 +302,7 @@ func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
return event == uint32(windows.WAIT_TIMEOUT), err
}
-func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
+func (p *Process) PpidWithContext(_ context.Context) (int32, error) {
// if cached already, return from cache
cachedPpid := p.getPpid()
if cachedPpid != 0 {
@@ -330,17 +330,17 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
exe, err := p.ExeWithContext(ctx)
if err != nil {
- return "", fmt.Errorf("could not get Name: %s", err)
+ return "", fmt.Errorf("could not get Name: %w", err)
}
return filepath.Base(exe), nil
}
-func (p *Process) TgidWithContext(ctx context.Context) (int32, error) {
+func (p *Process) TgidWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
+func (p *Process) ExeWithContext(_ context.Context) (string, error) {
c, err := windows.OpenProcess(processQueryInformation, false, uint32(p.Pid))
if err != nil {
return "", err
@@ -357,20 +357,20 @@ func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
if ret == 0 {
return "", err
}
- return windows.UTF16ToString(buf[:]), nil
+ return windows.UTF16ToString(buf), nil
}
// XP fallback
ret, _, err := procGetProcessImageFileNameW.Call(uintptr(c), uintptr(unsafe.Pointer(&buf[0])), uintptr(size))
if ret == 0 {
return "", err
}
- return common.ConvertDOSPath(windows.UTF16ToString(buf[:])), nil
+ return common.ConvertDOSPath(windows.UTF16ToString(buf)), nil
}
func (p *Process) CmdlineWithContext(_ context.Context) (string, error) {
cmdline, err := getProcessCommandLine(p.Pid)
if err != nil {
- return "", fmt.Errorf("could not get CommandLine: %s", err)
+ return "", fmt.Errorf("could not get CommandLine: %w", err)
}
return cmdline, nil
}
@@ -380,13 +380,33 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error)
if err != nil {
return nil, err
}
- return strings.Split(cmdline, " "), nil
+ return parseCmdline(cmdline)
}
-func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
+func parseCmdline(cmdline string) ([]string, error) {
+ cmdlineptr, err := windows.UTF16PtrFromString(cmdline)
+ if err != nil {
+ return nil, err
+ }
+
+ var argc int32
+ argvptr, err := windows.CommandLineToArgv(cmdlineptr, &argc)
+ if err != nil {
+ return nil, err
+ }
+ defer windows.LocalFree(windows.Handle(uintptr(unsafe.Pointer(argvptr))))
+
+ argv := make([]string, argc)
+ for i, v := range (*argvptr)[:argc] {
+ argv[i] = windows.UTF16ToString((*v)[:])
+ }
+ return argv, nil
+}
+
+func (p *Process) createTimeWithContext(_ context.Context) (int64, error) {
ru, err := getRusage(p.Pid)
if err != nil {
- return 0, fmt.Errorf("could not get CreationDate: %s", err)
+ return 0, fmt.Errorf("could not get CreationDate: %w", err)
}
return ru.CreationTime.Nanoseconds() / 1000000, nil
@@ -394,7 +414,7 @@ func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
func (p *Process) CwdWithContext(_ context.Context) (string, error) {
h, err := windows.OpenProcess(processQueryInformation|windows.PROCESS_VM_READ, false, uint32(p.Pid))
- if err == windows.ERROR_ACCESS_DENIED || err == windows.ERROR_INVALID_PARAMETER {
+ if errors.Is(err, windows.ERROR_ACCESS_DENIED) || errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
return "", nil
}
if err != nil {
@@ -436,15 +456,15 @@ func (p *Process) CwdWithContext(_ context.Context) (string, error) {
return "", nil
}
-func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
+func (p *Process) StatusWithContext(_ context.Context) ([]string, error) {
return []string{""}, common.ErrNotImplementedError
}
-func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
+func (p *Process) ForegroundWithContext(_ context.Context) (bool, error) {
return false, common.ErrNotImplementedError
}
-func (p *Process) UsernameWithContext(ctx context.Context) (string, error) {
+func (p *Process) UsernameWithContext(_ context.Context) (string, error) {
pid := p.Pid
c, err := windows.OpenProcess(processQueryInformation, false, uint32(pid))
if err != nil {
@@ -467,19 +487,19 @@ func (p *Process) UsernameWithContext(ctx context.Context) (string, error) {
return domain + "\\" + user, err
}
-func (p *Process) UidsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) UidsWithContext(_ context.Context) ([]uint32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) GidsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) GidsWithContext(_ context.Context) ([]uint32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) GroupsWithContext(ctx context.Context) ([]uint32, error) {
+func (p *Process) GroupsWithContext(_ context.Context) ([]uint32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
+func (p *Process) TerminalWithContext(_ context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
@@ -495,7 +515,7 @@ var priorityClasses = map[int]int32{
0x00000100: 24, // REALTIME_PRIORITY_CLASS
}
-func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NiceWithContext(_ context.Context) (int32, error) {
c, err := windows.OpenProcess(processQueryInformation, false, uint32(p.Pid))
if err != nil {
return 0, err
@@ -512,19 +532,19 @@ func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
return priority, nil
}
-func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) {
+func (p *Process) IOniceWithContext(_ context.Context) (int32, error) {
return 0, common.ErrNotImplementedError
}
-func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
+func (p *Process) RlimitWithContext(_ context.Context) ([]RlimitStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
+func (p *Process) RlimitUsageWithContext(_ context.Context, _ bool) ([]RlimitStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
+func (p *Process) IOCountersWithContext(_ context.Context) (*IOCountersStat, error) {
c, err := windows.OpenProcess(processQueryInformation, false, uint32(p.Pid))
if err != nil {
return nil, err
@@ -545,13 +565,13 @@ func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, e
return stats, nil
}
-func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
+func (p *Process) NumCtxSwitchesWithContext(_ context.Context) (*NumCtxSwitchesStat, error) {
return nil, common.ErrNotImplementedError
}
// NumFDsWithContext returns the number of handles for a process on Windows,
// not the number of file descriptors (FDs).
-func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NumFDsWithContext(_ context.Context) (int32, error) {
handle, err := windows.OpenProcess(processQueryInformation, false, uint32(p.Pid))
if err != nil {
return 0, err
@@ -566,7 +586,7 @@ func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
return int32(handleCount), nil
}
-func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
+func (p *Process) NumThreadsWithContext(_ context.Context) (int32, error) {
ppid, ret, _, err := getFromSnapProcess(p.Pid)
if err != nil {
return 0, err
@@ -581,11 +601,11 @@ func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
return ret, nil
}
-func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
+func (p *Process) ThreadsWithContext(_ context.Context) (map[int32]*cpu.TimesStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
+func (p *Process) TimesWithContext(_ context.Context) (*cpu.TimesStat, error) {
sysTimes, err := getProcessCPUTimes(p.Pid)
if err != nil {
return nil, err
@@ -609,11 +629,11 @@ func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error)
}, nil
}
-func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
+func (p *Process) CPUAffinityWithContext(_ context.Context) ([]int32, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
+func (p *Process) MemoryInfoWithContext(_ context.Context) (*MemoryInfoStat, error) {
mem, err := getMemoryInfo(p.Pid)
if err != nil {
return nil, err
@@ -627,12 +647,22 @@ func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, e
return ret, nil
}
-func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
+func (p *Process) MemoryInfoExWithContext(_ context.Context) (*MemoryInfoExStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
- return nil, common.ErrNotImplementedError
+func (p *Process) PageFaultsWithContext(_ context.Context) (*PageFaultsStat, error) {
+ mem, err := getMemoryInfo(p.Pid)
+ if err != nil {
+ return nil, err
+ }
+
+ ret := &PageFaultsStat{
+ // Since Windows does not distinguish between Major and Minor faults, all faults are treated as Major
+ MajorFaults: uint64(mem.PageFaultCount),
+ }
+
+ return ret, nil
}
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
@@ -758,19 +788,19 @@ func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionS
return net.ConnectionsPidWithContext(ctx, "all", p.Pid)
}
-func (p *Process) ConnectionsMaxWithContext(ctx context.Context, maxConn int) ([]net.ConnectionStat, error) {
+func (p *Process) ConnectionsMaxWithContext(_ context.Context, _ int) ([]net.ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
+func (p *Process) MemoryMapsWithContext(_ context.Context, _ bool) (*[]MemoryMapsStat, error) {
return nil, common.ErrNotImplementedError
}
-func (p *Process) SendSignalWithContext(ctx context.Context, sig syscall.Signal) error {
+func (p *Process) SendSignalWithContext(_ context.Context, _ syscall.Signal) error {
return common.ErrNotImplementedError
}
-func (p *Process) SuspendWithContext(ctx context.Context) error {
+func (p *Process) SuspendWithContext(_ context.Context) error {
c, err := windows.OpenProcess(windows.PROCESS_SUSPEND_RESUME, false, uint32(p.Pid))
if err != nil {
return err
@@ -786,7 +816,7 @@ func (p *Process) SuspendWithContext(ctx context.Context) error {
return nil
}
-func (p *Process) ResumeWithContext(ctx context.Context) error {
+func (p *Process) ResumeWithContext(_ context.Context) error {
c, err := windows.OpenProcess(windows.PROCESS_SUSPEND_RESUME, false, uint32(p.Pid))
if err != nil {
return err
@@ -802,7 +832,7 @@ func (p *Process) ResumeWithContext(ctx context.Context) error {
return nil
}
-func (p *Process) TerminateWithContext(ctx context.Context) error {
+func (p *Process) TerminateWithContext(_ context.Context) error {
proc, err := windows.OpenProcess(windows.PROCESS_TERMINATE, false, uint32(p.Pid))
if err != nil {
return err
@@ -812,7 +842,7 @@ func (p *Process) TerminateWithContext(ctx context.Context) error {
return err
}
-func (p *Process) KillWithContext(ctx context.Context) error {
+func (p *Process) KillWithContext(_ context.Context) error {
process, err := os.FindProcess(int(p.Pid))
if err != nil {
return err
@@ -822,9 +852,9 @@ func (p *Process) KillWithContext(ctx context.Context) error {
}
func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) {
- envVars, err := getProcessEnvironmentVariables(p.Pid, ctx)
+ envVars, err := getProcessEnvironmentVariables(ctx, p.Pid)
if err != nil {
- return nil, fmt.Errorf("could not get environment variables: %s", err)
+ return nil, fmt.Errorf("could not get environment variables: %w", err)
}
return envVars, nil
}
@@ -844,7 +874,7 @@ func (p *Process) setPpid(ppid int32) {
p.parent = ppid
}
-func getFromSnapProcess(pid int32) (int32, int32, string, error) {
+func getFromSnapProcess(pid int32) (int32, int32, string, error) { //nolint:unparam //FIXME
snap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, uint32(pid))
if err != nil {
return 0, 0, "", err
@@ -872,7 +902,7 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
pids, err := PidsWithContext(ctx)
if err != nil {
- return out, fmt.Errorf("could not get Processes %s", err)
+ return out, fmt.Errorf("could not get Processes %w", err)
}
for _, pid := range pids {
@@ -928,7 +958,7 @@ func getProcessMemoryInfo(h windows.Handle, mem *PROCESS_MEMORY_COUNTERS) (err e
return
}
-type SYSTEM_TIMES struct {
+type SYSTEM_TIMES struct { //nolint:revive //FIXME
CreateTime syscall.Filetime
ExitTime syscall.Filetime
KernelTime syscall.Filetime
@@ -963,13 +993,13 @@ func getUserProcessParams32(handle windows.Handle) (rtlUserProcessParameters32,
buf := readProcessMemory(syscall.Handle(handle), true, pebAddress, uint(unsafe.Sizeof(processEnvironmentBlock32{})))
if len(buf) != int(unsafe.Sizeof(processEnvironmentBlock32{})) {
- return rtlUserProcessParameters32{}, fmt.Errorf("cannot read process PEB")
+ return rtlUserProcessParameters32{}, errors.New("cannot read process PEB")
}
peb := (*processEnvironmentBlock32)(unsafe.Pointer(&buf[0]))
userProcessAddress := uint64(peb.ProcessParameters)
buf = readProcessMemory(syscall.Handle(handle), true, userProcessAddress, uint(unsafe.Sizeof(rtlUserProcessParameters32{})))
if len(buf) != int(unsafe.Sizeof(rtlUserProcessParameters32{})) {
- return rtlUserProcessParameters32{}, fmt.Errorf("cannot read user process parameters")
+ return rtlUserProcessParameters32{}, errors.New("cannot read user process parameters")
}
return *(*rtlUserProcessParameters32)(unsafe.Pointer(&buf[0])), nil
}
@@ -982,13 +1012,13 @@ func getUserProcessParams64(handle windows.Handle) (rtlUserProcessParameters64,
buf := readProcessMemory(syscall.Handle(handle), false, pebAddress, uint(unsafe.Sizeof(processEnvironmentBlock64{})))
if len(buf) != int(unsafe.Sizeof(processEnvironmentBlock64{})) {
- return rtlUserProcessParameters64{}, fmt.Errorf("cannot read process PEB")
+ return rtlUserProcessParameters64{}, errors.New("cannot read process PEB")
}
peb := (*processEnvironmentBlock64)(unsafe.Pointer(&buf[0]))
userProcessAddress := peb.ProcessParameters
buf = readProcessMemory(syscall.Handle(handle), false, userProcessAddress, uint(unsafe.Sizeof(rtlUserProcessParameters64{})))
if len(buf) != int(unsafe.Sizeof(rtlUserProcessParameters64{})) {
- return rtlUserProcessParameters64{}, fmt.Errorf("cannot read user process parameters")
+ return rtlUserProcessParameters64{}, errors.New("cannot read user process parameters")
}
return *(*rtlUserProcessParameters64)(unsafe.Pointer(&buf[0])), nil
}
@@ -1038,9 +1068,9 @@ func is32BitProcess(h windows.Handle) bool {
return procIs32Bits
}
-func getProcessEnvironmentVariables(pid int32, ctx context.Context) ([]string, error) {
+func getProcessEnvironmentVariables(ctx context.Context, pid int32) ([]string, error) {
h, err := windows.OpenProcess(processQueryInformation|windows.PROCESS_VM_READ, false, uint32(pid))
- if err == windows.ERROR_ACCESS_DENIED || err == windows.ERROR_INVALID_PARAMETER {
+ if errors.Is(err, windows.ERROR_ACCESS_DENIED) || errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
return nil, nil
}
if err != nil {
@@ -1124,7 +1154,7 @@ func (p *processReader) Read(buf []byte) (int, error) {
func getProcessCommandLine(pid int32) (string, error) {
h, err := windows.OpenProcess(processQueryInformation|windows.PROCESS_VM_READ, false, uint32(pid))
- if err == windows.ERROR_ACCESS_DENIED || err == windows.ERROR_INVALID_PARAMETER {
+ if errors.Is(err, windows.ERROR_ACCESS_DENIED) || errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
return "", nil
}
if err != nil {
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_windows_32bit.go b/vendor/github.com/shirou/gopsutil/v4/process/process_windows_32bit.go
index 2b231c7..911351b 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_windows_32bit.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_windows_32bit.go
@@ -8,11 +8,12 @@ import (
"syscall"
"unsafe"
- "github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows"
+
+ "github.com/shirou/gopsutil/v4/internal/common"
)
-type PROCESS_MEMORY_COUNTERS struct {
+type PROCESS_MEMORY_COUNTERS struct { //nolint:revive //FIXME
CB uint32
PageFaultCount uint32
PeakWorkingSetSize uint32
@@ -39,30 +40,27 @@ func queryPebAddress(procHandle syscall.Handle, is32BitProcess bool) (uint64, er
)
if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
return uint64(info.PebBaseAddress), nil
- } else {
- return 0, windows.NTStatus(ret)
}
- } else {
- // we are on a 32-bit process reading an external 64-bit process
- if common.ProcNtWow64QueryInformationProcess64.Find() == nil { // avoid panic
- var info processBasicInformation64
+ return 0, windows.NTStatus(ret)
+ }
+ // we are on a 32-bit process reading an external 64-bit process
+ if common.ProcNtWow64QueryInformationProcess64.Find() != nil {
+ return 0, errors.New("can't find API to query 64 bit process from 32 bit")
+ }
+ // avoid panic
+ var info processBasicInformation64
- ret, _, _ := common.ProcNtWow64QueryInformationProcess64.Call(
- uintptr(procHandle),
- uintptr(common.ProcessBasicInformation),
- uintptr(unsafe.Pointer(&info)),
- uintptr(unsafe.Sizeof(info)),
- uintptr(0),
- )
- if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
- return info.PebBaseAddress, nil
- } else {
- return 0, windows.NTStatus(ret)
- }
- } else {
- return 0, errors.New("can't find API to query 64 bit process from 32 bit")
- }
+ ret, _, _ := common.ProcNtWow64QueryInformationProcess64.Call(
+ uintptr(procHandle),
+ uintptr(common.ProcessBasicInformation),
+ uintptr(unsafe.Pointer(&info)),
+ uintptr(unsafe.Sizeof(info)),
+ uintptr(0),
+ )
+ if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
+ return info.PebBaseAddress, nil
}
+ return 0, windows.NTStatus(ret)
}
func readProcessMemory(h syscall.Handle, is32BitProcess bool, address uint64, size uint) []byte {
@@ -81,25 +79,23 @@ func readProcessMemory(h syscall.Handle, is32BitProcess bool, address uint64, si
if int(ret) >= 0 && read > 0 {
return buffer[:read]
}
- } else {
// reading a 64-bit process from a 32-bit one
- if common.ProcNtWow64ReadVirtualMemory64.Find() == nil { // avoid panic
- var read uint64
+ } else if common.ProcNtWow64ReadVirtualMemory64.Find() == nil { // avoid panic
+ var read uint64
- buffer := make([]byte, size)
+ buffer := make([]byte, size)
- ret, _, _ := common.ProcNtWow64ReadVirtualMemory64.Call(
- uintptr(h),
- uintptr(address&0xFFFFFFFF), // the call expects a 64-bit value
- uintptr(address>>32),
- uintptr(unsafe.Pointer(&buffer[0])),
- uintptr(size), // the call expects a 64-bit value
- uintptr(0), // but size is 32-bit so pass zero as the high dword
- uintptr(unsafe.Pointer(&read)),
- )
- if int(ret) >= 0 && read > 0 {
- return buffer[:uint(read)]
- }
+ ret, _, _ := common.ProcNtWow64ReadVirtualMemory64.Call(
+ uintptr(h),
+ uintptr(address&0xFFFFFFFF), // the call expects a 64-bit value
+ uintptr(address>>32),
+ uintptr(unsafe.Pointer(&buffer[0])),
+ uintptr(size), // the call expects a 64-bit value
+ uintptr(0), // but size is 32-bit so pass zero as the high dword
+ uintptr(unsafe.Pointer(&read)),
+ )
+ if int(ret) >= 0 && read > 0 {
+ return buffer[:uint(read)]
}
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_windows_64bit.go b/vendor/github.com/shirou/gopsutil/v4/process/process_windows_64bit.go
index befe521..8cc26c3 100644
--- a/vendor/github.com/shirou/gopsutil/v4/process/process_windows_64bit.go
+++ b/vendor/github.com/shirou/gopsutil/v4/process/process_windows_64bit.go
@@ -7,11 +7,12 @@ import (
"syscall"
"unsafe"
- "github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows"
+
+ "github.com/shirou/gopsutil/v4/internal/common"
)
-type PROCESS_MEMORY_COUNTERS struct {
+type PROCESS_MEMORY_COUNTERS struct { //nolint:revive //FIXME
CB uint32
PageFaultCount uint32
PeakWorkingSetSize uint64
@@ -38,26 +39,23 @@ func queryPebAddress(procHandle syscall.Handle, is32BitProcess bool) (uint64, er
)
if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
return uint64(wow64), nil
- } else {
- return 0, windows.NTStatus(ret)
}
- } else {
- // we are on a 64-bit process reading an external 64-bit process
- var info processBasicInformation64
+ return 0, windows.NTStatus(ret)
+ }
+ // we are on a 64-bit process reading an external 64-bit process
+ var info processBasicInformation64
- ret, _, _ := common.ProcNtQueryInformationProcess.Call(
- uintptr(procHandle),
- uintptr(common.ProcessBasicInformation),
- uintptr(unsafe.Pointer(&info)),
- uintptr(unsafe.Sizeof(info)),
- uintptr(0),
- )
- if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
- return info.PebBaseAddress, nil
- } else {
- return 0, windows.NTStatus(ret)
- }
+ ret, _, _ := common.ProcNtQueryInformationProcess.Call(
+ uintptr(procHandle),
+ uintptr(common.ProcessBasicInformation),
+ uintptr(unsafe.Pointer(&info)),
+ uintptr(unsafe.Sizeof(info)),
+ uintptr(0),
+ )
+ if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
+ return info.PebBaseAddress, nil
}
+ return 0, windows.NTStatus(ret)
}
func readProcessMemory(procHandle syscall.Handle, _ bool, address uint64, size uint) []byte {
diff --git a/vendor/github.com/tklauser/go-sysconf/.cirrus.yml b/vendor/github.com/tklauser/go-sysconf/.cirrus.yml
index 1b27f19..495e5e6 100644
--- a/vendor/github.com/tklauser/go-sysconf/.cirrus.yml
+++ b/vendor/github.com/tklauser/go-sysconf/.cirrus.yml
@@ -1,10 +1,10 @@
env:
CIRRUS_CLONE_DEPTH: 1
- GO_VERSION: go1.20
+ GO_VERSION: go1.24.0
-freebsd_12_task:
+freebsd_13_task:
freebsd_instance:
- image_family: freebsd-12-3
+ image_family: freebsd-13-5
install_script: |
pkg install -y go
GOBIN=$PWD/bin go install golang.org/dl/${GO_VERSION}@latest
@@ -12,9 +12,9 @@ freebsd_12_task:
build_script: bin/${GO_VERSION} build -v ./...
test_script: bin/${GO_VERSION} test -race ./...
-freebsd_13_task:
+freebsd_14_task:
freebsd_instance:
- image_family: freebsd-13-0
+ image_family: freebsd-14-2
install_script: |
pkg install -y go
GOBIN=$PWD/bin go install golang.org/dl/${GO_VERSION}@latest
diff --git a/vendor/github.com/tklauser/go-sysconf/sysconf_bsd.go b/vendor/github.com/tklauser/go-sysconf/sysconf_bsd.go
index 7c96157..ec81c02 100644
--- a/vendor/github.com/tklauser/go-sysconf/sysconf_bsd.go
+++ b/vendor/github.com/tklauser/go-sysconf/sysconf_bsd.go
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build darwin || dragonfly || freebsd || netbsd || openbsd
-// +build darwin dragonfly freebsd netbsd openbsd
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/sysconf_darwin.go b/vendor/github.com/tklauser/go-sysconf/sysconf_darwin.go
index 3f5d83f..b471ec1 100644
--- a/vendor/github.com/tklauser/go-sysconf/sysconf_darwin.go
+++ b/vendor/github.com/tklauser/go-sysconf/sysconf_darwin.go
@@ -16,6 +16,10 @@ const (
_HOST_NAME_MAX = _MAXHOSTNAMELEN - 1
_LOGIN_NAME_MAX = _MAXLOGNAME
_SYMLOOP_MAX = _MAXSYMLINKS
+
+ // _PTHREAD_STACK_MIN changed in macOS 14
+ _PTHREAD_STACK_MIN_LT_MACOS14 = 0x2000
+ _PTHREAD_STACK_MIN_GE_MACOS14 = 0x4000
)
var uname struct {
@@ -23,6 +27,21 @@ var uname struct {
macOSMajor int
}
+func getMacOSMajor() int {
+ uname.Once.Do(func() {
+ var u unix.Utsname
+ err := unix.Uname(&u)
+ if err != nil {
+ return
+ }
+ rel := unix.ByteSliceToString(u.Release[:])
+ ver := strings.Split(rel, ".")
+ maj, _ := strconv.Atoi(ver[0])
+ uname.macOSMajor = maj
+ })
+ return uname.macOSMajor
+}
+
// sysconf implements sysconf(4) as in the Darwin libc (derived from the FreeBSD
// libc), version 1534.81.1.
// See https://github.com/apple-oss-distributions/Libc/tree/Libc-1534.81.1.
@@ -91,7 +110,10 @@ func sysconf(name int) (int64, error) {
case SC_THREAD_PRIO_PROTECT:
return _POSIX_THREAD_PRIO_PROTECT, nil
case SC_THREAD_STACK_MIN:
- return _PTHREAD_STACK_MIN, nil
+ if getMacOSMajor() < 23 {
+ return _PTHREAD_STACK_MIN_LT_MACOS14, nil
+ }
+ return _PTHREAD_STACK_MIN_GE_MACOS14, nil
case SC_THREAD_THREADS_MAX:
return -1, nil
case SC_TIMER_MAX:
@@ -140,18 +162,7 @@ func sysconf(name int) (int64, error) {
}
return _POSIX_SEMAPHORES, nil
case SC_SPAWN:
- uname.Once.Do(func() {
- var u unix.Utsname
- err := unix.Uname(&u)
- if err != nil {
- return
- }
- rel := unix.ByteSliceToString(u.Release[:])
- ver := strings.Split(rel, ".")
- maj, _ := strconv.Atoi(ver[0])
- uname.macOSMajor = maj
- })
- if uname.macOSMajor < 22 {
+ if getMacOSMajor() < 22 {
return -1, nil
}
// macOS 13 (Ventura) and later
diff --git a/vendor/github.com/tklauser/go-sysconf/sysconf_generic.go b/vendor/github.com/tklauser/go-sysconf/sysconf_generic.go
index 248bdc9..7dcc6f4 100644
--- a/vendor/github.com/tklauser/go-sysconf/sysconf_generic.go
+++ b/vendor/github.com/tklauser/go-sysconf/sysconf_generic.go
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
-// +build darwin dragonfly freebsd linux netbsd openbsd
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/sysconf_linux.go b/vendor/github.com/tklauser/go-sysconf/sysconf_linux.go
index 5fb49ac..9af7007 100644
--- a/vendor/github.com/tklauser/go-sysconf/sysconf_linux.go
+++ b/vendor/github.com/tklauser/go-sysconf/sysconf_linux.go
@@ -6,7 +6,6 @@ package sysconf
import (
"bufio"
- "io/ioutil"
"os"
"runtime"
"strconv"
@@ -26,7 +25,7 @@ const (
)
func readProcFsInt64(path string, fallback int64) int64 {
- data, err := ioutil.ReadFile(path)
+ data, err := os.ReadFile(path)
if err != nil {
return fallback
}
@@ -86,10 +85,16 @@ func getNprocsProcStat() (int64, error) {
s := bufio.NewScanner(f)
for s.Scan() {
if line := strings.TrimSpace(s.Text()); strings.HasPrefix(line, "cpu") {
- l := strings.SplitN(line, " ", 2)
- _, err := strconv.ParseInt(l[0][3:], 10, 64)
- if err == nil {
- count++
+ cpu, _, found := strings.Cut(line, " ")
+ if found {
+ // skip first line with accumulated values
+ if cpu == "cpu" {
+ continue
+ }
+ _, err := strconv.ParseInt(cpu[len("cpu"):], 10, 64)
+ if err == nil {
+ count++
+ }
}
} else {
// The current format of /proc/stat has all the
@@ -98,6 +103,9 @@ func getNprocsProcStat() (int64, error) {
break
}
}
+ if err := s.Err(); err != nil {
+ return -1, err
+ }
return count, nil
}
diff --git a/vendor/github.com/tklauser/go-sysconf/sysconf_netbsd.go b/vendor/github.com/tklauser/go-sysconf/sysconf_netbsd.go
index 325d4a6..40f6c34 100644
--- a/vendor/github.com/tklauser/go-sysconf/sysconf_netbsd.go
+++ b/vendor/github.com/tklauser/go-sysconf/sysconf_netbsd.go
@@ -25,10 +25,10 @@ const (
_POSIX2_UPE = -1
)
-var (
- clktck int64
- clktckOnce sync.Once
-)
+var clktck struct {
+ sync.Once
+ v int64
+}
func sysconfPOSIX(name int) (int64, error) {
// NetBSD does not define all _POSIX_* values used in sysconf_posix.go
@@ -42,7 +42,6 @@ func sysconf(name int) (int64, error) {
// Duplicate the relevant values here.
switch name {
-
// 1003.1
case SC_ARG_MAX:
return sysctl32("kern.argmax"), nil
@@ -55,13 +54,14 @@ func sysconf(name int) (int64, error) {
}
return -1, nil
case SC_CLK_TCK:
- clktckOnce.Do(func() {
- clktck = -1
+ // TODO: use sync.OnceValue once Go 1.21 is the minimal supported version
+ clktck.Do(func() {
+ clktck.v = -1
if ci, err := unix.SysctlClockinfo("kern.clockrate"); err == nil {
- clktck = int64(ci.Hz)
+ clktck.v = int64(ci.Hz)
}
})
- return clktck, nil
+ return clktck.v, nil
case SC_NGROUPS_MAX:
return sysctl32("kern.ngroups"), nil
case SC_JOB_CONTROL:
diff --git a/vendor/github.com/tklauser/go-sysconf/sysconf_posix.go b/vendor/github.com/tklauser/go-sysconf/sysconf_posix.go
index e61c0bc..830d822 100644
--- a/vendor/github.com/tklauser/go-sysconf/sysconf_posix.go
+++ b/vendor/github.com/tklauser/go-sysconf/sysconf_posix.go
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build darwin || dragonfly || freebsd || linux || openbsd
-// +build darwin dragonfly freebsd linux openbsd
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/sysconf_unsupported.go b/vendor/github.com/tklauser/go-sysconf/sysconf_unsupported.go
index 478d692..5aa9119 100644
--- a/vendor/github.com/tklauser/go-sysconf/sysconf_unsupported.go
+++ b/vendor/github.com/tklauser/go-sysconf/sysconf_unsupported.go
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris
-// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_darwin.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_darwin.go
index 6fadf3d..80b6439 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_darwin.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_darwin.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_defs_darwin.go
//go:build darwin
-// +build darwin
package sysconf
@@ -235,7 +234,6 @@ const (
_PTHREAD_DESTRUCTOR_ITERATIONS = 0x4
_PTHREAD_KEYS_MAX = 0x200
- _PTHREAD_STACK_MIN = 0x2000
)
const (
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_dragonfly.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_dragonfly.go
index 0864cd4..dae5657 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_dragonfly.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_dragonfly.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_defs_dragonfly.go
//go:build dragonfly
-// +build dragonfly
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_freebsd.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_freebsd.go
index 9885411..068f8a7 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_freebsd.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_freebsd.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_defs_freebsd.go
//go:build freebsd
-// +build freebsd
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_linux.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_linux.go
index 8545a34..12f289d 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_linux.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_linux.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_defs_linux.go
//go:build linux
-// +build linux
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_netbsd.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_netbsd.go
index d2aaf07..772af47 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_netbsd.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_netbsd.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_defs_netbsd.go
//go:build netbsd
-// +build netbsd
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_openbsd.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_openbsd.go
index badc66c..625b098 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_openbsd.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_openbsd.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_defs_openbsd.go
//go:build openbsd
-// +build openbsd
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_solaris.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_solaris.go
index 29b6f87..c155cf5 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_solaris.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_defs_solaris.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_defs_solaris.go
//go:build solaris
-// +build solaris
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_386.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_386.go
index 478fe63..b5d4807 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_386.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_386.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_freebsd.go
//go:build freebsd && 386
-// +build freebsd,386
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_amd64.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_amd64.go
index 7f58a4d..89c880a 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_amd64.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_amd64.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_freebsd.go
//go:build freebsd && amd64
-// +build freebsd,amd64
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_arm.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_arm.go
index deb4759..7b65fdd 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_arm.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_arm.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_freebsd.go
//go:build freebsd && arm
-// +build freebsd,arm
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_arm64.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_arm64.go
index 556ba3d..a86cb32 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_arm64.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_arm64.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_freebsd.go
//go:build freebsd && arm64
-// +build freebsd,arm64
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_riscv64.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_riscv64.go
index b7cff76..6c847ae 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_riscv64.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_freebsd_riscv64.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_freebsd.go
//go:build freebsd && riscv64
-// +build freebsd,riscv64
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_386.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_386.go
index 16ee7ea..90963eb 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_386.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_386.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_linux.go
//go:build linux && 386
-// +build linux,386
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_amd64.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_amd64.go
index 39aee34..28ad6f1 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_amd64.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_amd64.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_linux.go
//go:build linux && amd64
-// +build linux,amd64
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_arm.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_arm.go
index 2e40116..ffbcf37 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_arm.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_arm.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_linux.go
//go:build linux && arm
-// +build linux,arm
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_arm64.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_arm64.go
index 362403a..cc9f4d8 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_arm64.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_arm64.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_linux.go
//go:build linux && arm64
-// +build linux,arm64
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_loong64.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_loong64.go
index 95a71f4..f62b15a 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_loong64.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_loong64.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_linux.go
//go:build linux && loong64
-// +build linux,loong64
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips.go
index 868b0ff..37f492a 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_linux.go
//go:build linux && mips
-// +build linux,mips
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips64.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips64.go
index 5949f3d..ae7b7f9 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips64.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips64.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_linux.go
//go:build linux && mips64
-// +build linux,mips64
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips64le.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips64le.go
index 1853419..fe14670 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips64le.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mips64le.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_linux.go
//go:build linux && mips64le
-// +build linux,mips64le
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mipsle.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mipsle.go
index ff41b34..d204585 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mipsle.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_mipsle.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_linux.go
//go:build linux && mipsle
-// +build linux,mipsle
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_ppc64.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_ppc64.go
index 3887437..9ec78d3 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_ppc64.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_ppc64.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_linux.go
//go:build linux && ppc64
-// +build linux,ppc64
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_ppc64le.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_ppc64le.go
index 6d76929..a542067 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_ppc64le.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_ppc64le.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_linux.go
//go:build linux && ppc64le
-// +build linux,ppc64le
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_riscv64.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_riscv64.go
index 3d7d71b..bfb9239 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_riscv64.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_riscv64.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_linux.go
//go:build linux && riscv64
-// +build linux,riscv64
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_s390x.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_s390x.go
index 9cf8529..6e935c8 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_s390x.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_linux_s390x.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_linux.go
//go:build linux && s390x
-// +build linux,s390x
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_386.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_386.go
index 3cd64dd..ea0b24a 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_386.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_386.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_netbsd.go
//go:build netbsd && 386
-// +build netbsd,386
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_amd64.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_amd64.go
index 02fc1d0..2d377e2 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_amd64.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_amd64.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_netbsd.go
//go:build netbsd && amd64
-// +build netbsd,amd64
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_arm.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_arm.go
index 16f9b6e..4a6d836 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_arm.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_arm.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_netbsd.go
//go:build netbsd && arm
-// +build netbsd,arm
package sysconf
diff --git a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_arm64.go b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_arm64.go
index e530339..49fb672 100644
--- a/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_arm64.go
+++ b/vendor/github.com/tklauser/go-sysconf/zsysconf_values_netbsd_arm64.go
@@ -2,7 +2,6 @@
// cgo -godefs sysconf_values_netbsd.go
//go:build netbsd && arm64
-// +build netbsd,arm64
package sysconf
diff --git a/vendor/github.com/tklauser/numcpus/.cirrus.yml b/vendor/github.com/tklauser/numcpus/.cirrus.yml
index 69c6ced..495e5e6 100644
--- a/vendor/github.com/tklauser/numcpus/.cirrus.yml
+++ b/vendor/github.com/tklauser/numcpus/.cirrus.yml
@@ -1,13 +1,23 @@
env:
CIRRUS_CLONE_DEPTH: 1
- GO_VERSION: go1.20
+ GO_VERSION: go1.24.0
-freebsd_12_task:
+freebsd_13_task:
freebsd_instance:
- image_family: freebsd-12-3
+ image_family: freebsd-13-5
install_script: |
pkg install -y go
GOBIN=$PWD/bin go install golang.org/dl/${GO_VERSION}@latest
bin/${GO_VERSION} download
- build_script: bin/${GO_VERSION} build -buildvcs=false -v ./...
- test_script: bin/${GO_VERSION} test -buildvcs=false -race ./...
+ build_script: bin/${GO_VERSION} build -v ./...
+ test_script: bin/${GO_VERSION} test -race ./...
+
+freebsd_14_task:
+ freebsd_instance:
+ image_family: freebsd-14-2
+ install_script: |
+ pkg install -y go
+ GOBIN=$PWD/bin go install golang.org/dl/${GO_VERSION}@latest
+ bin/${GO_VERSION} download
+ build_script: bin/${GO_VERSION} build -v ./...
+ test_script: bin/${GO_VERSION} test -race ./...
diff --git a/vendor/github.com/tklauser/numcpus/numcpus.go b/vendor/github.com/tklauser/numcpus/numcpus.go
index af59983..de206f0 100644
--- a/vendor/github.com/tklauser/numcpus/numcpus.go
+++ b/vendor/github.com/tklauser/numcpus/numcpus.go
@@ -73,3 +73,26 @@ func GetPossible() (int, error) {
func GetPresent() (int, error) {
return getPresent()
}
+
+// ListOffline returns the list of offline CPUs. See [GetOffline] for details on
+// when a CPU is considered offline.
+func ListOffline() ([]int, error) {
+ return listOffline()
+}
+
+// ListOnline returns the list of CPUs that are online and being scheduled.
+func ListOnline() ([]int, error) {
+ return listOnline()
+}
+
+// ListPossible returns the list of possible CPUs. See [GetPossible] for
+// details on when a CPU is considered possible.
+func ListPossible() ([]int, error) {
+ return listPossible()
+}
+
+// ListPresent returns the list of present CPUs. See [GetPresent] for
+// details on when a CPU is considered present.
+func ListPresent() ([]int, error) {
+ return listPresent()
+}
diff --git a/vendor/github.com/tklauser/numcpus/numcpus_bsd.go b/vendor/github.com/tklauser/numcpus/numcpus_bsd.go
index 9e77e38..efd8db0 100644
--- a/vendor/github.com/tklauser/numcpus/numcpus_bsd.go
+++ b/vendor/github.com/tklauser/numcpus/numcpus_bsd.go
@@ -13,7 +13,6 @@
// limitations under the License.
//go:build darwin || dragonfly || freebsd || netbsd || openbsd
-// +build darwin dragonfly freebsd netbsd openbsd
package numcpus
diff --git a/vendor/github.com/tklauser/numcpus/numcpus_linux.go b/vendor/github.com/tklauser/numcpus/numcpus_linux.go
index 1a30525..7b991da 100644
--- a/vendor/github.com/tklauser/numcpus/numcpus_linux.go
+++ b/vendor/github.com/tklauser/numcpus/numcpus_linux.go
@@ -15,7 +15,7 @@
package numcpus
import (
- "io/ioutil"
+ "fmt"
"os"
"path/filepath"
"strconv"
@@ -24,7 +24,14 @@ import (
"golang.org/x/sys/unix"
)
-const sysfsCPUBasePath = "/sys/devices/system/cpu"
+const (
+ sysfsCPUBasePath = "/sys/devices/system/cpu"
+
+ offline = "offline"
+ online = "online"
+ possible = "possible"
+ present = "present"
+)
func getFromCPUAffinity() (int, error) {
var cpuSet unix.CPUSet
@@ -34,38 +41,83 @@ func getFromCPUAffinity() (int, error) {
return cpuSet.Count(), nil
}
-func readCPURange(file string) (int, error) {
- buf, err := ioutil.ReadFile(filepath.Join(sysfsCPUBasePath, file))
+func readCPURangeWith[T any](file string, f func(cpus string) (T, error)) (T, error) {
+ var zero T
+ buf, err := os.ReadFile(filepath.Join(sysfsCPUBasePath, file))
if err != nil {
- return 0, err
+ return zero, err
}
- return parseCPURange(strings.Trim(string(buf), "\n "))
+ return f(strings.Trim(string(buf), "\n "))
}
-func parseCPURange(cpus string) (int, error) {
+func countCPURange(cpus string) (int, error) {
+ // Treat empty file as valid. This might be the case if there are no offline CPUs in which
+ // case /sys/devices/system/cpu/offline is empty.
+ if cpus == "" {
+ return 0, nil
+ }
+
n := int(0)
for _, cpuRange := range strings.Split(cpus, ",") {
- if len(cpuRange) == 0 {
- continue
+ if cpuRange == "" {
+ return 0, fmt.Errorf("empty CPU range in CPU string %q", cpus)
}
- rangeOp := strings.SplitN(cpuRange, "-", 2)
- first, err := strconv.ParseUint(rangeOp[0], 10, 32)
+ from, to, found := strings.Cut(cpuRange, "-")
+ first, err := strconv.ParseUint(from, 10, 32)
if err != nil {
return 0, err
}
- if len(rangeOp) == 1 {
+ if !found {
n++
continue
}
- last, err := strconv.ParseUint(rangeOp[1], 10, 32)
+ last, err := strconv.ParseUint(to, 10, 32)
if err != nil {
return 0, err
}
+ if last < first {
+ return 0, fmt.Errorf("last CPU in range (%d) less than first (%d)", last, first)
+ }
n += int(last - first + 1)
}
return n, nil
}
+func listCPURange(cpus string) ([]int, error) {
+ // See comment in countCPURange.
+ if cpus == "" {
+ return []int{}, nil
+ }
+
+ list := []int{}
+ for _, cpuRange := range strings.Split(cpus, ",") {
+ if cpuRange == "" {
+ return nil, fmt.Errorf("empty CPU range in CPU string %q", cpus)
+ }
+ from, to, found := strings.Cut(cpuRange, "-")
+ first, err := strconv.ParseUint(from, 10, 32)
+ if err != nil {
+ return nil, err
+ }
+ if !found {
+ // range containing a single element
+ list = append(list, int(first))
+ continue
+ }
+ last, err := strconv.ParseUint(to, 10, 32)
+ if err != nil {
+ return nil, err
+ }
+ if last < first {
+ return nil, fmt.Errorf("last CPU in range (%d) less than first (%d)", last, first)
+ }
+ for cpu := int(first); cpu <= int(last); cpu++ {
+ list = append(list, cpu)
+ }
+ }
+ return list, nil
+}
+
func getConfigured() (int, error) {
d, err := os.Open(sysfsCPUBasePath)
if err != nil {
@@ -89,7 +141,7 @@ func getConfigured() (int, error) {
}
func getKernelMax() (int, error) {
- buf, err := ioutil.ReadFile(filepath.Join(sysfsCPUBasePath, "kernel_max"))
+ buf, err := os.ReadFile(filepath.Join(sysfsCPUBasePath, "kernel_max"))
if err != nil {
return 0, err
}
@@ -101,20 +153,36 @@ func getKernelMax() (int, error) {
}
func getOffline() (int, error) {
- return readCPURange("offline")
+ return readCPURangeWith(offline, countCPURange)
}
func getOnline() (int, error) {
if n, err := getFromCPUAffinity(); err == nil {
return n, nil
}
- return readCPURange("online")
+ return readCPURangeWith(online, countCPURange)
}
func getPossible() (int, error) {
- return readCPURange("possible")
+ return readCPURangeWith(possible, countCPURange)
}
func getPresent() (int, error) {
- return readCPURange("present")
+ return readCPURangeWith(present, countCPURange)
+}
+
+func listOffline() ([]int, error) {
+ return readCPURangeWith(offline, listCPURange)
+}
+
+func listOnline() ([]int, error) {
+ return readCPURangeWith(online, listCPURange)
+}
+
+func listPossible() ([]int, error) {
+ return readCPURangeWith(possible, listCPURange)
+}
+
+func listPresent() ([]int, error) {
+ return readCPURangeWith(present, listCPURange)
}
diff --git a/vendor/github.com/tklauser/numcpus/numcpus_list_unsupported.go b/vendor/github.com/tklauser/numcpus/numcpus_list_unsupported.go
new file mode 100644
index 0000000..af4efea
--- /dev/null
+++ b/vendor/github.com/tklauser/numcpus/numcpus_list_unsupported.go
@@ -0,0 +1,33 @@
+// Copyright 2024 Tobias Klauser
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//go:build !linux
+
+package numcpus
+
+func listOffline() ([]int, error) {
+ return nil, ErrNotSupported
+}
+
+func listOnline() ([]int, error) {
+ return nil, ErrNotSupported
+}
+
+func listPossible() ([]int, error) {
+ return nil, ErrNotSupported
+}
+
+func listPresent() ([]int, error) {
+ return nil, ErrNotSupported
+}
diff --git a/vendor/github.com/tklauser/numcpus/numcpus_solaris.go b/vendor/github.com/tklauser/numcpus/numcpus_solaris.go
index a264323..f3b632f 100644
--- a/vendor/github.com/tklauser/numcpus/numcpus_solaris.go
+++ b/vendor/github.com/tklauser/numcpus/numcpus_solaris.go
@@ -13,7 +13,6 @@
// limitations under the License.
//go:build solaris
-// +build solaris
package numcpus
diff --git a/vendor/github.com/tklauser/numcpus/numcpus_unsupported.go b/vendor/github.com/tklauser/numcpus/numcpus_unsupported.go
index 4a0b7c4..e72355e 100644
--- a/vendor/github.com/tklauser/numcpus/numcpus_unsupported.go
+++ b/vendor/github.com/tklauser/numcpus/numcpus_unsupported.go
@@ -13,7 +13,6 @@
// limitations under the License.
//go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows
-// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
package numcpus
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/client.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/client.go
index 6aae83b..b25641c 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/client.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/client.go
@@ -18,7 +18,7 @@ var DefaultClient = &http.Client{Transport: NewTransport(http.DefaultTransport)}
// Get is a convenient replacement for http.Get that adds a span around the request.
func Get(ctx context.Context, targetURL string) (resp *http.Response, err error) {
- req, err := http.NewRequestWithContext(ctx, "GET", targetURL, nil)
+ req, err := http.NewRequestWithContext(ctx, http.MethodGet, targetURL, nil)
if err != nil {
return nil, err
}
@@ -27,7 +27,7 @@ func Get(ctx context.Context, targetURL string) (resp *http.Response, err error)
// Head is a convenient replacement for http.Head that adds a span around the request.
func Head(ctx context.Context, targetURL string) (resp *http.Response, err error) {
- req, err := http.NewRequestWithContext(ctx, "HEAD", targetURL, nil)
+ req, err := http.NewRequestWithContext(ctx, http.MethodHead, targetURL, nil)
if err != nil {
return nil, err
}
@@ -36,7 +36,7 @@ func Head(ctx context.Context, targetURL string) (resp *http.Response, err error
// Post is a convenient replacement for http.Post that adds a span around the request.
func Post(ctx context.Context, targetURL, contentType string, body io.Reader) (resp *http.Response, err error) {
- req, err := http.NewRequestWithContext(ctx, "POST", targetURL, body)
+ req, err := http.NewRequestWithContext(ctx, http.MethodPost, targetURL, body)
if err != nil {
return nil, err
}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go
index 5d6e615..a83a026 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go
@@ -18,13 +18,6 @@ const (
WriteErrorKey = attribute.Key("http.write_error") // if an error occurred while writing a reply, the string of the error (io.EOF is not recorded)
)
-// Client HTTP metrics.
-const (
- clientRequestSize = "http.client.request.size" // Outgoing request bytes total
- clientResponseSize = "http.client.response.size" // Outgoing response bytes total
- clientDuration = "http.client.duration" // Outgoing end to end duration, milliseconds
-)
-
// Filter is a predicate used to determine whether a given http.request should
// be traced. A Filter must return true if the request should be traced.
type Filter func(*http.Request) bool
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go
index 33580a3..3ea05d0 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go
@@ -12,6 +12,7 @@ import (
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
"go.opentelemetry.io/otel"
+ "go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"
)
@@ -21,15 +22,16 @@ type middleware struct {
operation string
server string
- tracer trace.Tracer
- propagators propagation.TextMapPropagator
- spanStartOptions []trace.SpanStartOption
- readEvent bool
- writeEvent bool
- filters []Filter
- spanNameFormatter func(string, *http.Request) string
- publicEndpoint bool
- publicEndpointFn func(*http.Request) bool
+ tracer trace.Tracer
+ propagators propagation.TextMapPropagator
+ spanStartOptions []trace.SpanStartOption
+ readEvent bool
+ writeEvent bool
+ filters []Filter
+ spanNameFormatter func(string, *http.Request) string
+ publicEndpoint bool
+ publicEndpointFn func(*http.Request) bool
+ metricAttributesFn func(*http.Request) []attribute.KeyValue
semconv semconv.HTTPServer
}
@@ -79,12 +81,7 @@ func (h *middleware) configure(c *config) {
h.publicEndpointFn = c.PublicEndpointFn
h.server = c.ServerName
h.semconv = semconv.NewHTTPServer(c.Meter)
-}
-
-func handleErr(err error) {
- if err != nil {
- otel.Handle(err)
- }
+ h.metricAttributesFn = c.MetricAttributesFn
}
// serveHTTP sets up tracing and calls the given next http.Handler with the span
@@ -123,6 +120,11 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
}
}
+ if startTime := StartTimeFromContext(ctx); !startTime.IsZero() {
+ opts = append(opts, trace.WithTimestamp(startTime))
+ requestStartTime = startTime
+ }
+
ctx, span := tracer.Start(ctx, h.spanNameFormatter(h.operation, r), opts...)
defer span.End()
@@ -190,17 +192,31 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
// Use floating point division here for higher precision (instead of Millisecond method).
elapsedTime := float64(time.Since(requestStartTime)) / float64(time.Millisecond)
- h.semconv.RecordMetrics(ctx, semconv.MetricData{
- ServerName: h.server,
+ metricAttributes := semconv.MetricAttributes{
Req: r,
StatusCode: statusCode,
- AdditionalAttributes: labeler.Get(),
- RequestSize: bw.BytesRead(),
- ResponseSize: bytesWritten,
- ElapsedTime: elapsedTime,
+ AdditionalAttributes: append(labeler.Get(), h.metricAttributesFromRequest(r)...),
+ }
+
+ h.semconv.RecordMetrics(ctx, semconv.ServerMetricData{
+ ServerName: h.server,
+ ResponseSize: bytesWritten,
+ MetricAttributes: metricAttributes,
+ MetricData: semconv.MetricData{
+ RequestSize: bw.BytesRead(),
+ ElapsedTime: elapsedTime,
+ },
})
}
+func (h *middleware) metricAttributesFromRequest(r *http.Request) []attribute.KeyValue {
+ var attributeForRequest []attribute.KeyValue
+ if h.metricAttributesFn != nil {
+ attributeForRequest = h.metricAttributesFn(r)
+ }
+ return attributeForRequest
+}
+
// WithRouteTag annotates spans and metrics with the provided route name
// with HTTP route attribute.
func WithRouteTag(route string, h http.Handler) http.Handler {
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go
index a945f55..866aa21 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go
@@ -1,3 +1,6 @@
+// Code created by gotmpl. DO NOT MODIFY.
+// source: internal/shared/request/body_wrapper.go.tmpl
+
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/gen.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/gen.go
new file mode 100644
index 0000000..9e00dd2
--- /dev/null
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/gen.go
@@ -0,0 +1,10 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package request // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request"
+
+// Generate request package:
+//go:generate gotmpl --body=../../../../../../internal/shared/request/body_wrapper.go.tmpl "--data={}" --out=body_wrapper.go
+//go:generate gotmpl --body=../../../../../../internal/shared/request/body_wrapper_test.go.tmpl "--data={}" --out=body_wrapper_test.go
+//go:generate gotmpl --body=../../../../../../internal/shared/request/resp_writer_wrapper.go.tmpl "--data={}" --out=resp_writer_wrapper.go
+//go:generate gotmpl --body=../../../../../../internal/shared/request/resp_writer_wrapper_test.go.tmpl "--data={}" --out=resp_writer_wrapper_test.go
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go
index aea171f..73184e7 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go
@@ -1,3 +1,6 @@
+// Code created by gotmpl. DO NOT MODIFY.
+// source: internal/shared/request/resp_writer_wrapper.go.tmpl
+
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
@@ -44,7 +47,9 @@ func (w *RespWriterWrapper) Write(p []byte) (int, error) {
w.mu.Lock()
defer w.mu.Unlock()
- w.writeHeader(http.StatusOK)
+ if !w.wroteHeader {
+ w.writeHeader(http.StatusOK)
+ }
n, err := w.ResponseWriter.Write(p)
n1 := int64(n)
@@ -80,7 +85,12 @@ func (w *RespWriterWrapper) writeHeader(statusCode int) {
// Flush implements [http.Flusher].
func (w *RespWriterWrapper) Flush() {
- w.WriteHeader(http.StatusOK)
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ if !w.wroteHeader {
+ w.writeHeader(http.StatusOK)
+ }
if f, ok := w.ResponseWriter.(http.Flusher); ok {
f.Flush()
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go
index 9cae4ca..4693a01 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go
@@ -1,3 +1,6 @@
+// Code created by gotmpl. DO NOT MODIFY.
+// source: internal/shared/semconv/env.go.tmpl
+
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
@@ -9,12 +12,17 @@ import (
"net/http"
"os"
"strings"
+ "sync"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/metric"
)
+// OTelSemConvStabilityOptIn is an environment variable.
+// That can be set to "old" or "http/dup" to opt into the new HTTP semantic conventions.
+const OTelSemConvStabilityOptIn = "OTEL_SEMCONV_STABILITY_OPT_IN"
+
type ResponseTelemetry struct {
StatusCode int
ReadBytes int64
@@ -30,6 +38,11 @@ type HTTPServer struct {
requestBytesCounter metric.Int64Counter
responseBytesCounter metric.Int64Counter
serverLatencyMeasure metric.Float64Histogram
+
+ // New metrics
+ requestBodySizeHistogram metric.Int64Histogram
+ responseBodySizeHistogram metric.Int64Histogram
+ requestDurationHistogram metric.Float64Histogram
}
// RequestTraceAttrs returns trace attributes for an HTTP request received by a
@@ -50,9 +63,18 @@ type HTTPServer struct {
// The req Host will be used to determine the server instead.
func (s HTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
if s.duplicate {
- return append(oldHTTPServer{}.RequestTraceAttrs(server, req), newHTTPServer{}.RequestTraceAttrs(server, req)...)
+ return append(OldHTTPServer{}.RequestTraceAttrs(server, req), CurrentHTTPServer{}.RequestTraceAttrs(server, req)...)
+ }
+ return OldHTTPServer{}.RequestTraceAttrs(server, req)
+}
+
+func (s HTTPServer) NetworkTransportAttr(network string) []attribute.KeyValue {
+ if s.duplicate {
+ return append([]attribute.KeyValue{OldHTTPServer{}.NetworkTransportAttr(network)}, CurrentHTTPServer{}.NetworkTransportAttr(network))
+ }
+ return []attribute.KeyValue{
+ OldHTTPServer{}.NetworkTransportAttr(network),
}
- return oldHTTPServer{}.RequestTraceAttrs(server, req)
}
// ResponseTraceAttrs returns trace attributes for telemetry from an HTTP response.
@@ -60,14 +82,14 @@ func (s HTTPServer) RequestTraceAttrs(server string, req *http.Request) []attrib
// If any of the fields in the ResponseTelemetry are not set the attribute will be omitted.
func (s HTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
if s.duplicate {
- return append(oldHTTPServer{}.ResponseTraceAttrs(resp), newHTTPServer{}.ResponseTraceAttrs(resp)...)
+ return append(OldHTTPServer{}.ResponseTraceAttrs(resp), CurrentHTTPServer{}.ResponseTraceAttrs(resp)...)
}
- return oldHTTPServer{}.ResponseTraceAttrs(resp)
+ return OldHTTPServer{}.ResponseTraceAttrs(resp)
}
// Route returns the attribute for the route.
func (s HTTPServer) Route(route string) attribute.KeyValue {
- return oldHTTPServer{}.Route(route)
+ return OldHTTPServer{}.Route(route)
}
// Status returns a span status code and message for an HTTP status code
@@ -83,67 +105,120 @@ func (s HTTPServer) Status(code int) (codes.Code, string) {
return codes.Unset, ""
}
-type MetricData struct {
- ServerName string
+type ServerMetricData struct {
+ ServerName string
+ ResponseSize int64
+
+ MetricData
+ MetricAttributes
+}
+
+type MetricAttributes struct {
Req *http.Request
StatusCode int
AdditionalAttributes []attribute.KeyValue
+}
- RequestSize int64
- ResponseSize int64
- ElapsedTime float64
+type MetricData struct {
+ RequestSize int64
+ ElapsedTime float64
}
-func (s HTTPServer) RecordMetrics(ctx context.Context, md MetricData) {
- if s.requestBytesCounter == nil || s.responseBytesCounter == nil || s.serverLatencyMeasure == nil {
- // This will happen if an HTTPServer{} is used insted of NewHTTPServer.
- return
+var (
+ metricAddOptionPool = &sync.Pool{
+ New: func() interface{} {
+ return &[]metric.AddOption{}
+ },
+ }
+
+ metricRecordOptionPool = &sync.Pool{
+ New: func() interface{} {
+ return &[]metric.RecordOption{}
+ },
}
+)
- attributes := oldHTTPServer{}.MetricAttributes(md.ServerName, md.Req, md.StatusCode, md.AdditionalAttributes)
- o := metric.WithAttributeSet(attribute.NewSet(attributes...))
- addOpts := []metric.AddOption{o} // Allocate vararg slice once.
- s.requestBytesCounter.Add(ctx, md.RequestSize, addOpts...)
- s.responseBytesCounter.Add(ctx, md.ResponseSize, addOpts...)
- s.serverLatencyMeasure.Record(ctx, md.ElapsedTime, o)
+func (s HTTPServer) RecordMetrics(ctx context.Context, md ServerMetricData) {
+ if s.requestBytesCounter != nil && s.responseBytesCounter != nil && s.serverLatencyMeasure != nil {
+ attributes := OldHTTPServer{}.MetricAttributes(md.ServerName, md.Req, md.StatusCode, md.AdditionalAttributes)
+ o := metric.WithAttributeSet(attribute.NewSet(attributes...))
+ addOpts := metricAddOptionPool.Get().(*[]metric.AddOption)
+ *addOpts = append(*addOpts, o)
+ s.requestBytesCounter.Add(ctx, md.RequestSize, *addOpts...)
+ s.responseBytesCounter.Add(ctx, md.ResponseSize, *addOpts...)
+ s.serverLatencyMeasure.Record(ctx, md.ElapsedTime, o)
+ *addOpts = (*addOpts)[:0]
+ metricAddOptionPool.Put(addOpts)
+ }
- // TODO: Duplicate Metrics
+ if s.duplicate && s.requestDurationHistogram != nil && s.requestBodySizeHistogram != nil && s.responseBodySizeHistogram != nil {
+ attributes := CurrentHTTPServer{}.MetricAttributes(md.ServerName, md.Req, md.StatusCode, md.AdditionalAttributes)
+ o := metric.WithAttributeSet(attribute.NewSet(attributes...))
+ recordOpts := metricRecordOptionPool.Get().(*[]metric.RecordOption)
+ *recordOpts = append(*recordOpts, o)
+ s.requestBodySizeHistogram.Record(ctx, md.RequestSize, *recordOpts...)
+ s.responseBodySizeHistogram.Record(ctx, md.ResponseSize, *recordOpts...)
+ s.requestDurationHistogram.Record(ctx, md.ElapsedTime, o)
+ *recordOpts = (*recordOpts)[:0]
+ metricRecordOptionPool.Put(recordOpts)
+ }
}
func NewHTTPServer(meter metric.Meter) HTTPServer {
- env := strings.ToLower(os.Getenv("OTEL_SEMCONV_STABILITY_OPT_IN"))
+ env := strings.ToLower(os.Getenv(OTelSemConvStabilityOptIn))
duplicate := env == "http/dup"
server := HTTPServer{
duplicate: duplicate,
}
- server.requestBytesCounter, server.responseBytesCounter, server.serverLatencyMeasure = oldHTTPServer{}.createMeasures(meter)
+ server.requestBytesCounter, server.responseBytesCounter, server.serverLatencyMeasure = OldHTTPServer{}.createMeasures(meter)
+ if duplicate {
+ server.requestBodySizeHistogram, server.responseBodySizeHistogram, server.requestDurationHistogram = CurrentHTTPServer{}.createMeasures(meter)
+ }
return server
}
type HTTPClient struct {
duplicate bool
+
+ // old metrics
+ requestBytesCounter metric.Int64Counter
+ responseBytesCounter metric.Int64Counter
+ latencyMeasure metric.Float64Histogram
+
+ // new metrics
+ requestBodySize metric.Int64Histogram
+ requestDuration metric.Float64Histogram
}
-func NewHTTPClient() HTTPClient {
- env := strings.ToLower(os.Getenv("OTEL_SEMCONV_STABILITY_OPT_IN"))
- return HTTPClient{duplicate: env == "http/dup"}
+func NewHTTPClient(meter metric.Meter) HTTPClient {
+ env := strings.ToLower(os.Getenv(OTelSemConvStabilityOptIn))
+ duplicate := env == "http/dup"
+ client := HTTPClient{
+ duplicate: duplicate,
+ }
+ client.requestBytesCounter, client.responseBytesCounter, client.latencyMeasure = OldHTTPClient{}.createMeasures(meter)
+ if duplicate {
+ client.requestBodySize, client.requestDuration = CurrentHTTPClient{}.createMeasures(meter)
+ }
+
+ return client
}
// RequestTraceAttrs returns attributes for an HTTP request made by a client.
func (c HTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
if c.duplicate {
- return append(oldHTTPClient{}.RequestTraceAttrs(req), newHTTPClient{}.RequestTraceAttrs(req)...)
+ return append(OldHTTPClient{}.RequestTraceAttrs(req), CurrentHTTPClient{}.RequestTraceAttrs(req)...)
}
- return oldHTTPClient{}.RequestTraceAttrs(req)
+ return OldHTTPClient{}.RequestTraceAttrs(req)
}
// ResponseTraceAttrs returns metric attributes for an HTTP request made by a client.
func (c HTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
if c.duplicate {
- return append(oldHTTPClient{}.ResponseTraceAttrs(resp), newHTTPClient{}.ResponseTraceAttrs(resp)...)
+ return append(OldHTTPClient{}.ResponseTraceAttrs(resp), CurrentHTTPClient{}.ResponseTraceAttrs(resp)...)
}
- return oldHTTPClient{}.ResponseTraceAttrs(resp)
+ return OldHTTPClient{}.ResponseTraceAttrs(resp)
}
func (c HTTPClient) Status(code int) (codes.Code, string) {
@@ -158,8 +233,75 @@ func (c HTTPClient) Status(code int) (codes.Code, string) {
func (c HTTPClient) ErrorType(err error) attribute.KeyValue {
if c.duplicate {
- return newHTTPClient{}.ErrorType(err)
+ return CurrentHTTPClient{}.ErrorType(err)
}
return attribute.KeyValue{}
}
+
+type MetricOpts struct {
+ measurement metric.MeasurementOption
+ addOptions metric.AddOption
+}
+
+func (o MetricOpts) MeasurementOption() metric.MeasurementOption {
+ return o.measurement
+}
+
+func (o MetricOpts) AddOptions() metric.AddOption {
+ return o.addOptions
+}
+
+func (c HTTPClient) MetricOptions(ma MetricAttributes) map[string]MetricOpts {
+ opts := map[string]MetricOpts{}
+
+ attributes := OldHTTPClient{}.MetricAttributes(ma.Req, ma.StatusCode, ma.AdditionalAttributes)
+ set := metric.WithAttributeSet(attribute.NewSet(attributes...))
+ opts["old"] = MetricOpts{
+ measurement: set,
+ addOptions: set,
+ }
+
+ if c.duplicate {
+ attributes := CurrentHTTPClient{}.MetricAttributes(ma.Req, ma.StatusCode, ma.AdditionalAttributes)
+ set := metric.WithAttributeSet(attribute.NewSet(attributes...))
+ opts["new"] = MetricOpts{
+ measurement: set,
+ addOptions: set,
+ }
+ }
+
+ return opts
+}
+
+func (s HTTPClient) RecordMetrics(ctx context.Context, md MetricData, opts map[string]MetricOpts) {
+ if s.requestBytesCounter == nil || s.latencyMeasure == nil {
+ // This will happen if an HTTPClient{} is used instead of NewHTTPClient().
+ return
+ }
+
+ s.requestBytesCounter.Add(ctx, md.RequestSize, opts["old"].AddOptions())
+ s.latencyMeasure.Record(ctx, md.ElapsedTime, opts["old"].MeasurementOption())
+
+ if s.duplicate {
+ s.requestBodySize.Record(ctx, md.RequestSize, opts["new"].MeasurementOption())
+ s.requestDuration.Record(ctx, md.ElapsedTime, opts["new"].MeasurementOption())
+ }
+}
+
+func (s HTTPClient) RecordResponseSize(ctx context.Context, responseData int64, opts map[string]MetricOpts) {
+ if s.responseBytesCounter == nil {
+ // This will happen if an HTTPClient{} is used instead of NewHTTPClient().
+ return
+ }
+
+ s.responseBytesCounter.Add(ctx, responseData, opts["old"].AddOptions())
+}
+
+func (s HTTPClient) TraceAttributes(host string) []attribute.KeyValue {
+ if s.duplicate {
+ return append(OldHTTPClient{}.TraceAttributes(host), CurrentHTTPClient{}.TraceAttributes(host)...)
+ }
+
+ return OldHTTPClient{}.TraceAttributes(host)
+}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/gen.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/gen.go
new file mode 100644
index 0000000..f2cf8a1
--- /dev/null
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/gen.go
@@ -0,0 +1,14 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package semconv // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
+
+// Generate semconv package:
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/bench_test.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=bench_test.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/env.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=env.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/env_test.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=env_test.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/httpconv.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=httpconv.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/httpconv_test.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=httpconv_test.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/util.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=util.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/util_test.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=util_test.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/v1.20.0.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=v1.20.0.go
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go
index 745b8c6..8b85eff 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go
@@ -1,3 +1,6 @@
+// Code created by gotmpl. DO NOT MODIFY.
+// source: internal/shared/semconv/httpconv.go.tmpl
+
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
@@ -7,14 +10,17 @@ import (
"fmt"
"net/http"
"reflect"
+ "slices"
"strconv"
"strings"
"go.opentelemetry.io/otel/attribute"
+ "go.opentelemetry.io/otel/metric"
+ "go.opentelemetry.io/otel/metric/noop"
semconvNew "go.opentelemetry.io/otel/semconv/v1.26.0"
)
-type newHTTPServer struct{}
+type CurrentHTTPServer struct{}
// TraceRequest returns trace attributes for an HTTP request received by a
// server.
@@ -32,18 +38,18 @@ type newHTTPServer struct{}
//
// If the primary server name is not known, server should be an empty string.
// The req Host will be used to determine the server instead.
-func (n newHTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
+func (n CurrentHTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
count := 3 // ServerAddress, Method, Scheme
var host string
var p int
if server == "" {
- host, p = splitHostPort(req.Host)
+ host, p = SplitHostPort(req.Host)
} else {
// Prioritize the primary server name.
- host, p = splitHostPort(server)
+ host, p = SplitHostPort(server)
if p < 0 {
- _, p = splitHostPort(req.Host)
+ _, p = SplitHostPort(req.Host)
}
}
@@ -59,7 +65,7 @@ func (n newHTTPServer) RequestTraceAttrs(server string, req *http.Request) []att
scheme := n.scheme(req.TLS != nil)
- if peer, peerPort := splitHostPort(req.RemoteAddr); peer != "" {
+ if peer, peerPort := SplitHostPort(req.RemoteAddr); peer != "" {
// The Go HTTP server sets RemoteAddr to "IP:port", this will not be a
// file-path that would be interpreted with a sock family.
count++
@@ -104,7 +110,7 @@ func (n newHTTPServer) RequestTraceAttrs(server string, req *http.Request) []att
attrs = append(attrs, methodOriginal)
}
- if peer, peerPort := splitHostPort(req.RemoteAddr); peer != "" {
+ if peer, peerPort := SplitHostPort(req.RemoteAddr); peer != "" {
// The Go HTTP server sets RemoteAddr to "IP:port", this will not be a
// file-path that would be interpreted with a sock family.
attrs = append(attrs, semconvNew.NetworkPeerAddress(peer))
@@ -135,7 +141,20 @@ func (n newHTTPServer) RequestTraceAttrs(server string, req *http.Request) []att
return attrs
}
-func (n newHTTPServer) method(method string) (attribute.KeyValue, attribute.KeyValue) {
+func (o CurrentHTTPServer) NetworkTransportAttr(network string) attribute.KeyValue {
+ switch network {
+ case "tcp", "tcp4", "tcp6":
+ return semconvNew.NetworkTransportTCP
+ case "udp", "udp4", "udp6":
+ return semconvNew.NetworkTransportUDP
+ case "unix", "unixgram", "unixpacket":
+ return semconvNew.NetworkTransportUnix
+ default:
+ return semconvNew.NetworkTransportPipe
+ }
+}
+
+func (n CurrentHTTPServer) method(method string) (attribute.KeyValue, attribute.KeyValue) {
if method == "" {
return semconvNew.HTTPRequestMethodGet, attribute.KeyValue{}
}
@@ -150,7 +169,7 @@ func (n newHTTPServer) method(method string) (attribute.KeyValue, attribute.KeyV
return semconvNew.HTTPRequestMethodGet, orig
}
-func (n newHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive
+func (n CurrentHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive
if https {
return semconvNew.URLScheme("https")
}
@@ -160,7 +179,7 @@ func (n newHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive
// TraceResponse returns trace attributes for telemetry from an HTTP response.
//
// If any of the fields in the ResponseTelemetry are not set the attribute will be omitted.
-func (n newHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
+func (n CurrentHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
var count int
if resp.ReadBytes > 0 {
@@ -195,14 +214,94 @@ func (n newHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.Ke
}
// Route returns the attribute for the route.
-func (n newHTTPServer) Route(route string) attribute.KeyValue {
+func (n CurrentHTTPServer) Route(route string) attribute.KeyValue {
return semconvNew.HTTPRoute(route)
}
-type newHTTPClient struct{}
+func (n CurrentHTTPServer) createMeasures(meter metric.Meter) (metric.Int64Histogram, metric.Int64Histogram, metric.Float64Histogram) {
+ if meter == nil {
+ return noop.Int64Histogram{}, noop.Int64Histogram{}, noop.Float64Histogram{}
+ }
+
+ var err error
+ requestBodySizeHistogram, err := meter.Int64Histogram(
+ semconvNew.HTTPServerRequestBodySizeName,
+ metric.WithUnit(semconvNew.HTTPServerRequestBodySizeUnit),
+ metric.WithDescription(semconvNew.HTTPServerRequestBodySizeDescription),
+ )
+ handleErr(err)
+
+ responseBodySizeHistogram, err := meter.Int64Histogram(
+ semconvNew.HTTPServerResponseBodySizeName,
+ metric.WithUnit(semconvNew.HTTPServerResponseBodySizeUnit),
+ metric.WithDescription(semconvNew.HTTPServerResponseBodySizeDescription),
+ )
+ handleErr(err)
+ requestDurationHistogram, err := meter.Float64Histogram(
+ semconvNew.HTTPServerRequestDurationName,
+ metric.WithUnit(semconvNew.HTTPServerRequestDurationUnit),
+ metric.WithDescription(semconvNew.HTTPServerRequestDurationDescription),
+ )
+ handleErr(err)
+
+ return requestBodySizeHistogram, responseBodySizeHistogram, requestDurationHistogram
+}
+
+func (n CurrentHTTPServer) MetricAttributes(server string, req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue {
+ num := len(additionalAttributes) + 3
+ var host string
+ var p int
+ if server == "" {
+ host, p = SplitHostPort(req.Host)
+ } else {
+ // Prioritize the primary server name.
+ host, p = SplitHostPort(server)
+ if p < 0 {
+ _, p = SplitHostPort(req.Host)
+ }
+ }
+ hostPort := requiredHTTPPort(req.TLS != nil, p)
+ if hostPort > 0 {
+ num++
+ }
+ protoName, protoVersion := netProtocol(req.Proto)
+ if protoName != "" {
+ num++
+ }
+ if protoVersion != "" {
+ num++
+ }
+
+ if statusCode > 0 {
+ num++
+ }
+
+ attributes := slices.Grow(additionalAttributes, num)
+ attributes = append(attributes,
+ semconvNew.HTTPRequestMethodKey.String(standardizeHTTPMethod(req.Method)),
+ n.scheme(req.TLS != nil),
+ semconvNew.ServerAddress(host))
+
+ if hostPort > 0 {
+ attributes = append(attributes, semconvNew.ServerPort(hostPort))
+ }
+ if protoName != "" {
+ attributes = append(attributes, semconvNew.NetworkProtocolName(protoName))
+ }
+ if protoVersion != "" {
+ attributes = append(attributes, semconvNew.NetworkProtocolVersion(protoVersion))
+ }
+
+ if statusCode > 0 {
+ attributes = append(attributes, semconvNew.HTTPResponseStatusCode(statusCode))
+ }
+ return attributes
+}
+
+type CurrentHTTPClient struct{}
// RequestTraceAttrs returns trace attributes for an HTTP request made by a client.
-func (n newHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
+func (n CurrentHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
/*
below attributes are returned:
- http.request.method
@@ -222,7 +321,7 @@ func (n newHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue
var requestHost string
var requestPort int
for _, hostport := range []string{urlHost, req.Header.Get("Host")} {
- requestHost, requestPort = splitHostPort(hostport)
+ requestHost, requestPort = SplitHostPort(hostport)
if requestHost != "" || requestPort > 0 {
break
}
@@ -284,7 +383,7 @@ func (n newHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue
}
// ResponseTraceAttrs returns trace attributes for an HTTP response made by a client.
-func (n newHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
+func (n CurrentHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
/*
below attributes are returned:
- http.response.status_code
@@ -311,7 +410,7 @@ func (n newHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyVa
return attrs
}
-func (n newHTTPClient) ErrorType(err error) attribute.KeyValue {
+func (n CurrentHTTPClient) ErrorType(err error) attribute.KeyValue {
t := reflect.TypeOf(err)
var value string
if t.PkgPath() == "" && t.Name() == "" {
@@ -328,7 +427,7 @@ func (n newHTTPClient) ErrorType(err error) attribute.KeyValue {
return semconvNew.ErrorTypeKey.String(value)
}
-func (n newHTTPClient) method(method string) (attribute.KeyValue, attribute.KeyValue) {
+func (n CurrentHTTPClient) method(method string) (attribute.KeyValue, attribute.KeyValue) {
if method == "" {
return semconvNew.HTTPRequestMethodGet, attribute.KeyValue{}
}
@@ -343,6 +442,98 @@ func (n newHTTPClient) method(method string) (attribute.KeyValue, attribute.KeyV
return semconvNew.HTTPRequestMethodGet, orig
}
+func (n CurrentHTTPClient) createMeasures(meter metric.Meter) (metric.Int64Histogram, metric.Float64Histogram) {
+ if meter == nil {
+ return noop.Int64Histogram{}, noop.Float64Histogram{}
+ }
+
+ var err error
+ requestBodySize, err := meter.Int64Histogram(
+ semconvNew.HTTPClientRequestBodySizeName,
+ metric.WithUnit(semconvNew.HTTPClientRequestBodySizeUnit),
+ metric.WithDescription(semconvNew.HTTPClientRequestBodySizeDescription),
+ )
+ handleErr(err)
+
+ requestDuration, err := meter.Float64Histogram(
+ semconvNew.HTTPClientRequestDurationName,
+ metric.WithUnit(semconvNew.HTTPClientRequestDurationUnit),
+ metric.WithDescription(semconvNew.HTTPClientRequestDurationDescription),
+ )
+ handleErr(err)
+
+ return requestBodySize, requestDuration
+}
+
+func (n CurrentHTTPClient) MetricAttributes(req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue {
+ num := len(additionalAttributes) + 2
+ var h string
+ if req.URL != nil {
+ h = req.URL.Host
+ }
+ var requestHost string
+ var requestPort int
+ for _, hostport := range []string{h, req.Header.Get("Host")} {
+ requestHost, requestPort = SplitHostPort(hostport)
+ if requestHost != "" || requestPort > 0 {
+ break
+ }
+ }
+
+ port := requiredHTTPPort(req.URL != nil && req.URL.Scheme == "https", requestPort)
+ if port > 0 {
+ num++
+ }
+
+ protoName, protoVersion := netProtocol(req.Proto)
+ if protoName != "" {
+ num++
+ }
+ if protoVersion != "" {
+ num++
+ }
+
+ if statusCode > 0 {
+ num++
+ }
+
+ attributes := slices.Grow(additionalAttributes, num)
+ attributes = append(attributes,
+ semconvNew.HTTPRequestMethodKey.String(standardizeHTTPMethod(req.Method)),
+ semconvNew.ServerAddress(requestHost),
+ n.scheme(req.TLS != nil),
+ )
+
+ if port > 0 {
+ attributes = append(attributes, semconvNew.ServerPort(port))
+ }
+ if protoName != "" {
+ attributes = append(attributes, semconvNew.NetworkProtocolName(protoName))
+ }
+ if protoVersion != "" {
+ attributes = append(attributes, semconvNew.NetworkProtocolVersion(protoVersion))
+ }
+
+ if statusCode > 0 {
+ attributes = append(attributes, semconvNew.HTTPResponseStatusCode(statusCode))
+ }
+ return attributes
+}
+
+// Attributes for httptrace.
+func (n CurrentHTTPClient) TraceAttributes(host string) []attribute.KeyValue {
+ return []attribute.KeyValue{
+ semconvNew.ServerAddress(host),
+ }
+}
+
+func (n CurrentHTTPClient) scheme(https bool) attribute.KeyValue { // nolint:revive
+ if https {
+ return semconvNew.URLScheme("https")
+ }
+ return semconvNew.URLScheme("http")
+}
+
func isErrorStatusCode(code int) bool {
return code >= 400 || code < 100
}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go
index e6e1492..315d3dd 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go
@@ -1,3 +1,6 @@
+// Code created by gotmpl. DO NOT MODIFY.
+// source: internal/shared/semconv/util.go.tmpl
+
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
@@ -14,14 +17,14 @@ import (
semconvNew "go.opentelemetry.io/otel/semconv/v1.26.0"
)
-// splitHostPort splits a network address hostport of the form "host",
+// SplitHostPort splits a network address hostport of the form "host",
// "host%zone", "[host]", "[host%zone], "host:port", "host%zone:port",
// "[host]:port", "[host%zone]:port", or ":port" into host or host%zone and
// port.
//
// An empty host is returned if it is not provided or unparsable. A negative
// port is returned if it is not provided or unparsable.
-func splitHostPort(hostport string) (host string, port int) {
+func SplitHostPort(hostport string) (host string, port int) {
port = -1
if strings.HasPrefix(hostport, "[") {
@@ -75,7 +78,16 @@ func serverClientIP(xForwardedFor string) string {
func netProtocol(proto string) (name string, version string) {
name, version, _ = strings.Cut(proto, "/")
- name = strings.ToLower(name)
+ switch name {
+ case "HTTP":
+ name = "http"
+ case "QUIC":
+ name = "quic"
+ case "SPDY":
+ name = "spdy"
+ default:
+ name = strings.ToLower(name)
+ }
return name, version
}
@@ -96,3 +108,13 @@ func handleErr(err error) {
otel.Handle(err)
}
}
+
+func standardizeHTTPMethod(method string) string {
+ method = strings.ToUpper(method)
+ switch method {
+ case http.MethodConnect, http.MethodDelete, http.MethodGet, http.MethodHead, http.MethodOptions, http.MethodPatch, http.MethodPost, http.MethodPut, http.MethodTrace:
+ default:
+ method = "_OTHER"
+ }
+ return method
+}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go
index c999b05..742c211 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go
@@ -1,3 +1,6 @@
+// Code created by gotmpl. DO NOT MODIFY.
+// source: internal/shared/semconv/v120.0.go.tmpl
+
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
@@ -8,7 +11,6 @@ import (
"io"
"net/http"
"slices"
- "strings"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil"
"go.opentelemetry.io/otel/attribute"
@@ -17,7 +19,7 @@ import (
semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
)
-type oldHTTPServer struct{}
+type OldHTTPServer struct{}
// RequestTraceAttrs returns trace attributes for an HTTP request received by a
// server.
@@ -35,14 +37,18 @@ type oldHTTPServer struct{}
//
// If the primary server name is not known, server should be an empty string.
// The req Host will be used to determine the server instead.
-func (o oldHTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
+func (o OldHTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
return semconvutil.HTTPServerRequest(server, req)
}
+func (o OldHTTPServer) NetworkTransportAttr(network string) attribute.KeyValue {
+ return semconvutil.NetTransport(network)
+}
+
// ResponseTraceAttrs returns trace attributes for telemetry from an HTTP response.
//
// If any of the fields in the ResponseTelemetry are not set the attribute will be omitted.
-func (o oldHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
+func (o OldHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
attributes := []attribute.KeyValue{}
if resp.ReadBytes > 0 {
@@ -67,7 +73,7 @@ func (o oldHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.Ke
}
// Route returns the attribute for the route.
-func (o oldHTTPServer) Route(route string) attribute.KeyValue {
+func (o OldHTTPServer) Route(route string) attribute.KeyValue {
return semconv.HTTPRoute(route)
}
@@ -84,7 +90,7 @@ const (
serverDuration = "http.server.duration" // Incoming end to end duration, milliseconds
)
-func (h oldHTTPServer) createMeasures(meter metric.Meter) (metric.Int64Counter, metric.Int64Counter, metric.Float64Histogram) {
+func (h OldHTTPServer) createMeasures(meter metric.Meter) (metric.Int64Counter, metric.Int64Counter, metric.Float64Histogram) {
if meter == nil {
return noop.Int64Counter{}, noop.Int64Counter{}, noop.Float64Histogram{}
}
@@ -113,17 +119,17 @@ func (h oldHTTPServer) createMeasures(meter metric.Meter) (metric.Int64Counter,
return requestBytesCounter, responseBytesCounter, serverLatencyMeasure
}
-func (o oldHTTPServer) MetricAttributes(server string, req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue {
+func (o OldHTTPServer) MetricAttributes(server string, req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue {
n := len(additionalAttributes) + 3
var host string
var p int
if server == "" {
- host, p = splitHostPort(req.Host)
+ host, p = SplitHostPort(req.Host)
} else {
// Prioritize the primary server name.
- host, p = splitHostPort(server)
+ host, p = SplitHostPort(server)
if p < 0 {
- _, p = splitHostPort(req.Host)
+ _, p = SplitHostPort(req.Host)
}
}
hostPort := requiredHTTPPort(req.TLS != nil, p)
@@ -144,7 +150,7 @@ func (o oldHTTPServer) MetricAttributes(server string, req *http.Request, status
attributes := slices.Grow(additionalAttributes, n)
attributes = append(attributes,
- o.methodMetric(req.Method),
+ semconv.HTTPMethod(standardizeHTTPMethod(req.Method)),
o.scheme(req.TLS != nil),
semconv.NetHostName(host))
@@ -164,29 +170,108 @@ func (o oldHTTPServer) MetricAttributes(server string, req *http.Request, status
return attributes
}
-func (o oldHTTPServer) methodMetric(method string) attribute.KeyValue {
- method = strings.ToUpper(method)
- switch method {
- case http.MethodConnect, http.MethodDelete, http.MethodGet, http.MethodHead, http.MethodOptions, http.MethodPatch, http.MethodPost, http.MethodPut, http.MethodTrace:
- default:
- method = "_OTHER"
- }
- return semconv.HTTPMethod(method)
-}
-
-func (o oldHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive
+func (o OldHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive
if https {
return semconv.HTTPSchemeHTTPS
}
return semconv.HTTPSchemeHTTP
}
-type oldHTTPClient struct{}
+type OldHTTPClient struct{}
-func (o oldHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
+func (o OldHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
return semconvutil.HTTPClientRequest(req)
}
-func (o oldHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
+func (o OldHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
return semconvutil.HTTPClientResponse(resp)
}
+
+func (o OldHTTPClient) MetricAttributes(req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue {
+ /* The following semantic conventions are returned if present:
+ http.method string
+ http.status_code int
+ net.peer.name string
+ net.peer.port int
+ */
+
+ n := 2 // method, peer name.
+ var h string
+ if req.URL != nil {
+ h = req.URL.Host
+ }
+ var requestHost string
+ var requestPort int
+ for _, hostport := range []string{h, req.Header.Get("Host")} {
+ requestHost, requestPort = SplitHostPort(hostport)
+ if requestHost != "" || requestPort > 0 {
+ break
+ }
+ }
+
+ port := requiredHTTPPort(req.URL != nil && req.URL.Scheme == "https", requestPort)
+ if port > 0 {
+ n++
+ }
+
+ if statusCode > 0 {
+ n++
+ }
+
+ attributes := slices.Grow(additionalAttributes, n)
+ attributes = append(attributes,
+ semconv.HTTPMethod(standardizeHTTPMethod(req.Method)),
+ semconv.NetPeerName(requestHost),
+ )
+
+ if port > 0 {
+ attributes = append(attributes, semconv.NetPeerPort(port))
+ }
+
+ if statusCode > 0 {
+ attributes = append(attributes, semconv.HTTPStatusCode(statusCode))
+ }
+ return attributes
+}
+
+// Client HTTP metrics.
+const (
+ clientRequestSize = "http.client.request.size" // Incoming request bytes total
+ clientResponseSize = "http.client.response.size" // Incoming response bytes total
+ clientDuration = "http.client.duration" // Incoming end to end duration, milliseconds
+)
+
+func (o OldHTTPClient) createMeasures(meter metric.Meter) (metric.Int64Counter, metric.Int64Counter, metric.Float64Histogram) {
+ if meter == nil {
+ return noop.Int64Counter{}, noop.Int64Counter{}, noop.Float64Histogram{}
+ }
+ requestBytesCounter, err := meter.Int64Counter(
+ clientRequestSize,
+ metric.WithUnit("By"),
+ metric.WithDescription("Measures the size of HTTP request messages."),
+ )
+ handleErr(err)
+
+ responseBytesCounter, err := meter.Int64Counter(
+ clientResponseSize,
+ metric.WithUnit("By"),
+ metric.WithDescription("Measures the size of HTTP response messages."),
+ )
+ handleErr(err)
+
+ latencyMeasure, err := meter.Float64Histogram(
+ clientDuration,
+ metric.WithUnit("ms"),
+ metric.WithDescription("Measures the duration of outbound HTTP requests."),
+ )
+ handleErr(err)
+
+ return requestBytesCounter, responseBytesCounter, latencyMeasure
+}
+
+// Attributes for httptrace.
+func (c OldHTTPClient) TraceAttributes(host string) []attribute.KeyValue {
+ return []attribute.KeyValue{
+ semconv.NetHostName(host),
+ }
+}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go
index b80a1db..de74fa2 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go
@@ -200,6 +200,15 @@ func splitHostPort(hostport string) (host string, port int) {
func netProtocol(proto string) (name string, version string) {
name, version, _ = strings.Cut(proto, "/")
- name = strings.ToLower(name)
+ switch name {
+ case "HTTP":
+ name = "http"
+ case "QUIC":
+ name = "quic"
+ case "SPDY":
+ name = "spdy"
+ default:
+ name = strings.ToLower(name)
+ }
return name, version
}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/start_time_context.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/start_time_context.go
new file mode 100644
index 0000000..9476ef0
--- /dev/null
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/start_time_context.go
@@ -0,0 +1,29 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
+
+import (
+ "context"
+ "time"
+)
+
+type startTimeContextKeyType int
+
+const startTimeContextKey startTimeContextKeyType = 0
+
+// ContextWithStartTime returns a new context with the provided start time. The
+// start time will be used for metrics and traces emitted by the
+// instrumentation. Only one labeller can be injected into the context.
+// Injecting it multiple times will override the previous calls.
+func ContextWithStartTime(parent context.Context, start time.Time) context.Context {
+ return context.WithValue(parent, startTimeContextKey, start)
+}
+
+// StartTimeFromContext retrieves a time.Time from the provided context if one
+// is available. If no start time was found in the provided context, a new,
+// zero start time is returned and the second return value is false.
+func StartTimeFromContext(ctx context.Context) time.Time {
+ t, _ := ctx.Value(startTimeContextKey).(time.Time)
+ return t
+}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go
index b4119d3..44b86ad 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go
@@ -13,11 +13,9 @@ import (
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
- "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
- "go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"
@@ -29,7 +27,6 @@ type Transport struct {
rt http.RoundTripper
tracer trace.Tracer
- meter metric.Meter
propagators propagation.TextMapPropagator
spanStartOptions []trace.SpanStartOption
filters []Filter
@@ -37,10 +34,7 @@ type Transport struct {
clientTrace func(context.Context) *httptrace.ClientTrace
metricAttributesFn func(*http.Request) []attribute.KeyValue
- semconv semconv.HTTPClient
- requestBytesCounter metric.Int64Counter
- responseBytesCounter metric.Int64Counter
- latencyMeasure metric.Float64Histogram
+ semconv semconv.HTTPClient
}
var _ http.RoundTripper = &Transport{}
@@ -57,8 +51,7 @@ func NewTransport(base http.RoundTripper, opts ...Option) *Transport {
}
t := Transport{
- rt: base,
- semconv: semconv.NewHTTPClient(),
+ rt: base,
}
defaultOpts := []Option{
@@ -68,46 +61,21 @@ func NewTransport(base http.RoundTripper, opts ...Option) *Transport {
c := newConfig(append(defaultOpts, opts...)...)
t.applyConfig(c)
- t.createMeasures()
return &t
}
func (t *Transport) applyConfig(c *config) {
t.tracer = c.Tracer
- t.meter = c.Meter
t.propagators = c.Propagators
t.spanStartOptions = c.SpanStartOptions
t.filters = c.Filters
t.spanNameFormatter = c.SpanNameFormatter
t.clientTrace = c.ClientTrace
+ t.semconv = semconv.NewHTTPClient(c.Meter)
t.metricAttributesFn = c.MetricAttributesFn
}
-func (t *Transport) createMeasures() {
- var err error
- t.requestBytesCounter, err = t.meter.Int64Counter(
- clientRequestSize,
- metric.WithUnit("By"),
- metric.WithDescription("Measures the size of HTTP request messages."),
- )
- handleErr(err)
-
- t.responseBytesCounter, err = t.meter.Int64Counter(
- clientResponseSize,
- metric.WithUnit("By"),
- metric.WithDescription("Measures the size of HTTP response messages."),
- )
- handleErr(err)
-
- t.latencyMeasure, err = t.meter.Float64Histogram(
- clientDuration,
- metric.WithUnit("ms"),
- metric.WithDescription("Measures the duration of outbound HTTP requests."),
- )
- handleErr(err)
-}
-
func defaultTransportFormatter(_ string, r *http.Request) string {
return "HTTP " + r.Method
}
@@ -177,16 +145,15 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) {
}
// metrics
- metricAttrs := append(append(labeler.Get(), semconvutil.HTTPClientRequestMetrics(r)...), t.metricAttributesFromRequest(r)...)
- if res.StatusCode > 0 {
- metricAttrs = append(metricAttrs, semconv.HTTPStatusCode(res.StatusCode))
- }
- o := metric.WithAttributeSet(attribute.NewSet(metricAttrs...))
+ metricOpts := t.semconv.MetricOptions(semconv.MetricAttributes{
+ Req: r,
+ StatusCode: res.StatusCode,
+ AdditionalAttributes: append(labeler.Get(), t.metricAttributesFromRequest(r)...),
+ })
- t.requestBytesCounter.Add(ctx, bw.BytesRead(), o)
// For handling response bytes we leverage a callback when the client reads the http response
readRecordFunc := func(n int64) {
- t.responseBytesCounter.Add(ctx, n, o)
+ t.semconv.RecordResponseSize(ctx, n, metricOpts)
}
// traces
@@ -198,9 +165,12 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) {
// Use floating point division here for higher precision (instead of Millisecond method).
elapsedTime := float64(time.Since(requestStartTime)) / float64(time.Millisecond)
- t.latencyMeasure.Record(ctx, elapsedTime, o)
+ t.semconv.RecordMetrics(ctx, semconv.MetricData{
+ RequestSize: bw.BytesRead(),
+ ElapsedTime: elapsedTime,
+ }, metricOpts)
- return res, err
+ return res, nil
}
func (t *Transport) metricAttributesFromRequest(r *http.Request) []attribute.KeyValue {
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go
index 502c1bd..1ec9a00 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go
@@ -5,7 +5,7 @@ package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http
// Version is the current release version of the otelhttp instrumentation.
func Version() string {
- return "0.54.0"
+ return "0.60.0"
// This string is updated by the pre_release.sh script during release
}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index e7c8468..f04cbea 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1,7 +1,7 @@
-# dario.cat/mergo v1.0.1
+# dario.cat/mergo v1.0.2
## explicit; go 1.13
dario.cat/mergo
-# github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1
+# github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c
## explicit; go 1.16
github.com/Azure/go-ansiterm
github.com/Azure/go-ansiterm/winterm
@@ -36,10 +36,13 @@ github.com/cpuguy83/dockercfg
# github.com/davecgh/go-spew v1.1.1
## explicit
github.com/davecgh/go-spew/spew
+# github.com/deckarep/golang-set/v2 v2.7.0
+## explicit; go 1.18
+github.com/deckarep/golang-set/v2
# github.com/distribution/reference v0.6.0
## explicit; go 1.20
github.com/distribution/reference
-# github.com/docker/docker v28.0.4+incompatible
+# github.com/docker/docker v28.1.1+incompatible
## explicit
github.com/docker/docker/api
github.com/docker/docker/api/types
@@ -77,7 +80,7 @@ github.com/docker/go-connections/tlsconfig
# github.com/docker/go-units v0.5.0
## explicit
github.com/docker/go-units
-# github.com/ebitengine/purego v0.8.2
+# github.com/ebitengine/purego v0.8.3
## explicit; go 1.18
github.com/ebitengine/purego
github.com/ebitengine/purego/internal/cgo
@@ -103,10 +106,13 @@ github.com/go-logr/logr/funcr
# github.com/go-logr/stdr v1.2.2
## explicit; go 1.16
github.com/go-logr/stdr
-# github.com/go-ole/go-ole v1.2.6
+# github.com/go-ole/go-ole v1.3.0
## explicit; go 1.12
github.com/go-ole/go-ole
github.com/go-ole/go-ole/oleutil
+# github.com/go-stack/stack v1.8.1
+## explicit; go 1.17
+github.com/go-stack/stack
# github.com/gogo/protobuf v1.3.2
## explicit; go 1.15
github.com/gogo/protobuf/proto
@@ -158,8 +164,8 @@ github.com/klauspost/compress/internal/le
github.com/klauspost/compress/internal/snapref
github.com/klauspost/compress/zstd
github.com/klauspost/compress/zstd/internal/xxhash
-# github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0
-## explicit; go 1.16
+# github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35
+## explicit; go 1.21
github.com/lufia/plan9stats
# github.com/magiconair/properties v1.8.10
## explicit; go 1.19
@@ -176,20 +182,27 @@ github.com/mitchellh/mapstructure
# github.com/moby/docker-image-spec v1.3.1
## explicit; go 1.18
github.com/moby/docker-image-spec/specs-go/v1
+# github.com/moby/go-archive v0.1.0
+## explicit; go 1.23.0
+github.com/moby/go-archive
+github.com/moby/go-archive/compression
+github.com/moby/go-archive/tarheader
# github.com/moby/patternmatcher v0.6.0
## explicit; go 1.19
github.com/moby/patternmatcher
github.com/moby/patternmatcher/ignorefile
-# github.com/moby/sys/sequential v0.5.0
+# github.com/moby/sys/atomicwriter v0.1.0
+## explicit; go 1.18
+# github.com/moby/sys/sequential v0.6.0
## explicit; go 1.17
github.com/moby/sys/sequential
-# github.com/moby/sys/user v0.1.0
+# github.com/moby/sys/user v0.4.0
## explicit; go 1.17
github.com/moby/sys/user
# github.com/moby/sys/userns v0.1.0
## explicit; go 1.21
github.com/moby/sys/userns
-# github.com/moby/term v0.5.0
+# github.com/moby/term v0.5.2
## explicit; go 1.18
github.com/moby/term
github.com/moby/term/windows
@@ -212,10 +225,15 @@ github.com/opencontainers/image-spec/specs-go/v1
# github.com/pkg/errors v0.9.1
## explicit
github.com/pkg/errors
+# github.com/playwright-community/playwright-go v0.5200.0
+## explicit; go 1.22
+github.com/playwright-community/playwright-go
+github.com/playwright-community/playwright-go/cmd/playwright
+github.com/playwright-community/playwright-go/internal/safe
# github.com/pmezard/go-difflib v1.0.0
## explicit
github.com/pmezard/go-difflib/difflib
-# github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c
+# github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55
## explicit; go 1.14
github.com/power-devops/perfstat
# github.com/rs/zerolog v1.34.0
@@ -226,8 +244,8 @@ github.com/rs/zerolog/internal/json
# github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
## explicit; go 1.13
github.com/sabhiram/go-gitignore
-# github.com/shirou/gopsutil/v4 v4.25.1
-## explicit; go 1.18
+# github.com/shirou/gopsutil/v4 v4.25.4
+## explicit; go 1.23
github.com/shirou/gopsutil/v4/common
github.com/shirou/gopsutil/v4/cpu
github.com/shirou/gopsutil/v4/internal/common
@@ -252,11 +270,11 @@ github.com/testcontainers/testcontainers-go/internal/core
github.com/testcontainers/testcontainers-go/internal/core/network
github.com/testcontainers/testcontainers-go/log
github.com/testcontainers/testcontainers-go/wait
-# github.com/tklauser/go-sysconf v0.3.12
-## explicit; go 1.13
+# github.com/tklauser/go-sysconf v0.3.15
+## explicit; go 1.23.0
github.com/tklauser/go-sysconf
-# github.com/tklauser/numcpus v0.6.1
-## explicit; go 1.13
+# github.com/tklauser/numcpus v0.10.0
+## explicit; go 1.23.0
github.com/tklauser/numcpus
# github.com/xlgmokha/x v0.0.0-20250507172007-444d6e509eb4
## explicit; go 1.23.0
@@ -278,8 +296,8 @@ github.com/yusufpapurcu/wmi
## explicit; go 1.22.0
go.opentelemetry.io/auto/sdk
go.opentelemetry.io/auto/sdk/internal/telemetry
-# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0
-## explicit; go 1.21
+# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0
+## explicit; go 1.22.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv
@@ -306,8 +324,6 @@ go.opentelemetry.io/otel/semconv/v1.26.0
go.opentelemetry.io/otel/metric
go.opentelemetry.io/otel/metric/embedded
go.opentelemetry.io/otel/metric/noop
-# go.opentelemetry.io/otel/sdk v1.35.0
-## explicit; go 1.22.0
# go.opentelemetry.io/otel/trace v1.35.0
## explicit; go 1.22.0
go.opentelemetry.io/otel/trace