diff --git a/README.md b/README.md index 02ac77d..f7e2c19 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![PkgGoDev](https://pkg.go.dev/badge/github.com/playwright-community/playwright-go)](https://pkg.go.dev/github.com/playwright-community/playwright-go) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](http://opensource.org/licenses/MIT) [![Go Report Card](https://goreportcard.com/badge/github.com/playwright-community/playwright-go)](https://goreportcard.com/report/github.com/playwright-community/playwright-go) ![Build Status](https://github.com/playwright-community/playwright-go/workflows/Go/badge.svg) -[![Join Slack](https://img.shields.io/badge/join-slack-infomational)](https://aka.ms/playwright-slack) [![Coverage Status](https://coveralls.io/repos/github/playwright-community/playwright-go/badge.svg?branch=main)](https://coveralls.io/github/playwright-community/playwright-go?branch=main) [![Chromium version](https://img.shields.io/badge/chromium-129.0.6668.29-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-130.0-blue.svg?logo=mozilla-firefox)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) +[![Join Slack](https://img.shields.io/badge/join-slack-infomational)](https://aka.ms/playwright-slack) [![Coverage Status](https://coveralls.io/repos/github/playwright-community/playwright-go/badge.svg?branch=main)](https://coveralls.io/github/playwright-community/playwright-go?branch=main) [![Chromium version](https://img.shields.io/badge/chromium-130.0.6723.31-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-131.0-blue.svg?logo=mozilla-firefox)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) [API reference](https://playwright.dev/docs/api/class-playwright) | [Example recipes](https://github.com/playwright-community/playwright-go/tree/main/examples) @@ -13,9 +13,9 @@ Playwright is a Go library to automate [Chromium](https://www.chromium.org/Home) | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 129.0.6668.29 | ✅ | ✅ | ✅ | +| Chromium 130.0.6723.31 | ✅ | ✅ | ✅ | | WebKit 18.0 | ✅ | ✅ | ✅ | -| Firefox 130.0 | ✅ | ✅ | ✅ | +| Firefox 131.0 | ✅ | ✅ | ✅ | Headless execution is supported for all the browsers on all platforms. diff --git a/browser_context.go b/browser_context.go index dc4f4a3..58c7c5b 100644 --- a/browser_context.go +++ b/browser_context.go @@ -44,7 +44,7 @@ func (b *browserContextImpl) SetDefaultNavigationTimeout(timeout float64) { func (b *browserContextImpl) setDefaultNavigationTimeoutImpl(timeout *float64) { b.timeoutSettings.SetDefaultNavigationTimeout(timeout) - b.channel.SendNoReply("setDefaultNavigationTimeoutNoReply", map[string]interface{}{ + b.channel.SendNoReply("setDefaultNavigationTimeoutNoReply", true, map[string]interface{}{ "timeout": timeout, }) } @@ -55,7 +55,7 @@ func (b *browserContextImpl) SetDefaultTimeout(timeout float64) { func (b *browserContextImpl) setDefaultTimeoutImpl(timeout *float64) { b.timeoutSettings.SetDefaultTimeout(timeout) - b.channel.SendNoReply("setDefaultTimeoutNoReply", map[string]interface{}{ + b.channel.SendNoReply("setDefaultTimeoutNoReply", true, map[string]interface{}{ "timeout": timeout, }) } diff --git a/browser_type.go b/browser_type.go index fd160b7..f3832d4 100644 --- a/browser_type.go +++ b/browser_type.go @@ -105,7 +105,7 @@ func (b *browserTypeImpl) Connect(wsEndpoint string, options ...BrowserTypeConne if err != nil { return nil, err } - jsonPipe := fromChannel(pipe.(map[string]interface{})["pipe"]).(*jsonPipe) + jsonPipe := fromChannel(pipe["pipe"]).(*jsonPipe) connection := newConnection(jsonPipe, localUtils) playwright, err := connection.Start() @@ -146,9 +146,9 @@ func (b *browserTypeImpl) ConnectOverCDP(endpointURL string, options ...BrowserT if err != nil { return nil, err } - browser := fromChannel(response.(map[string]interface{})["browser"]).(*browserImpl) + browser := fromChannel(response["browser"]).(*browserImpl) b.didLaunchBrowser(browser) - if defaultContext, ok := response.(map[string]interface{})["defaultContext"]; ok { + if defaultContext, ok := response["defaultContext"]; ok { context := fromChannel(defaultContext).(*browserContextImpl) b.didCreateContext(context, nil, nil) } diff --git a/channel.go b/channel.go index 29de05a..9f3c26b 100644 --- a/channel.go +++ b/channel.go @@ -18,46 +18,27 @@ func (c *channel) MarshalJSON() ([]byte, error) { func (c *channel) Send(method string, options ...interface{}) (interface{}, error) { return c.connection.WrapAPICall(func() (interface{}, error) { - return c.innerSend(method, false, options...) - }, false) + return c.innerSend(method, options...).GetResultValue() + }, c.owner.isInternalType) } -func (c *channel) SendReturnAsDict(method string, options ...interface{}) (interface{}, error) { - return c.connection.WrapAPICall(func() (interface{}, error) { - return c.innerSend(method, true, options...) - }, true) +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, returnAsDict bool, options ...interface{}) (interface{}, error) { +func (c *channel) innerSend(method string, options ...interface{}) *protocolCallback { params := transformOptions(options...) - callback, err := c.connection.sendMessageToServer(c.owner, method, params, false) - if err != nil { - return nil, err - } - result, err := callback.GetResult() - if err != nil { - return nil, err - } - if result == nil { - return nil, nil - } - if returnAsDict { - return result, nil - } - if mapV, ok := result.(map[string]interface{}); ok && len(mapV) <= 1 { - for key := range mapV { - return mapV[key], nil - } - return nil, nil - } - return result, nil + return c.connection.sendMessageToServer(c.owner, method, params, false) } -func (c *channel) SendNoReply(method string, options ...interface{}) { +func (c *channel) SendNoReply(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) - }, false) + return c.connection.sendMessageToServer(c.owner, method, params, true).GetResult() + }, isInternal) if err != nil { logger.Printf("SendNoReply failed: %v\n", err) } diff --git a/channel_owner.go b/channel_owner.go index 007be70..4e3a1f0 100644 --- a/channel_owner.go +++ b/channel_owner.go @@ -16,6 +16,7 @@ type channelOwner struct { initializer map[string]interface{} parent *channelOwner wasCollected bool + isInternalType bool } func (c *channelOwner) dispose(reason ...string) { @@ -48,7 +49,7 @@ func (c *channelOwner) setEventSubscriptionMapping(mapping map[string]string) { func (c *channelOwner) updateSubscription(event string, enabled bool) { protocolEvent, ok := c.eventToSubscriptionMapping[event] if ok { - c.channel.SendNoReply("updateSubscription", map[string]interface{}{ + c.channel.SendNoReply("updateSubscription", true, map[string]interface{}{ "event": protocolEvent, "enabled": enabled, }) @@ -95,18 +96,22 @@ func (c *channelOwner) createChannelOwner(self interface{}, parent *channelOwner c.eventToSubscriptionMapping = map[string]string{} } +func (c *channelOwner) markAsInternalType() { + c.isInternalType = true +} + type rootChannelOwner struct { channelOwner } func (r *rootChannelOwner) initialize() (*Playwright, error) { - result, err := r.channel.Send("initialize", map[string]interface{}{ + ret, err := r.channel.SendReturnAsDict("initialize", map[string]interface{}{ "sdkLanguage": "javascript", }) if err != nil { return nil, err } - return fromChannel(result).(*Playwright), nil + return fromChannel(ret["playwright"]).(*Playwright), nil } func newRootChannelOwner(connection *connection) *rootChannelOwner { diff --git a/connection.go b/connection.go index 9d593a2..ff2b1f6 100644 --- a/connection.go +++ b/connection.go @@ -20,11 +20,6 @@ var ( apiNameTransform = regexp.MustCompile(`(?U)\(\*(.+)(Impl)?\)`) ) -type result struct { - Data interface{} - Error error -} - type connection struct { transport transport apiZone sync.Map @@ -102,13 +97,9 @@ func (c *connection) Dispatch(msg *message) { return } if msg.Error != nil { - cb.SetResult(result{ - Error: parseError(msg.Error.Error), - }) + cb.SetError(parseError(msg.Error.Error)) } else { - cb.SetResult(result{ - Data: c.replaceGuidsWithChannels(msg.Result), - }) + cb.SetResult(c.replaceGuidsWithChannels(msg.Result).(map[string]interface{})) } return } @@ -191,16 +182,20 @@ func (c *connection) replaceGuidsWithChannels(payload interface{}) interface{} { return payload } -func (c *connection) sendMessageToServer(object *channelOwner, method string, params interface{}, noReply bool) (*protocolCallback, error) { +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 { - return nil, err + cb.SetError(err) + return } if object.wasCollected { - return nil, errors.New("The object has been collected to prevent unbounded heap growth.") + cb.SetError(errors.New("The object has been collected to prevent unbounded heap growth.")) + return } id := c.lastID.Add(1) - cb, _ := c.callbacks.LoadOrStore(id, newProtocolCallback(noReply, c.abort)) + c.callbacks.Store(id, cb) var ( metadata = make(map[string]interface{}, 0) stack = make([]map[string]interface{}, 0) @@ -225,10 +220,11 @@ func (c *connection) sendMessageToServer(object *channelOwner, method string, pa } if err := c.transport.Send(message); err != nil { - return nil, fmt.Errorf("could not send message: %w", err) + cb.SetError(fmt.Errorf("could not send message: %w", err)) + return } - return cb, nil + return } func (c *connection) setInTracing(isTracing bool) { @@ -327,41 +323,66 @@ func fromNullableChannel(v interface{}) interface{} { } type protocolCallback struct { - callback chan result - noReply bool - abort <-chan struct{} + done chan struct{} + noReply bool + abort <-chan struct{} + once sync.Once + value map[string]interface{} + err error } -func (pc *protocolCallback) SetResult(r result) { +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.callback <- r: + case <-pc.done: + return default: + pc.err = errors.New("Connection closed") + return } - return - case pc.callback <- r: } } -func (pc *protocolCallback) GetResult() (interface{}, error) { - if pc.noReply { - return nil, nil +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 } - select { - case result := <-pc.callback: - return result.Data, result.Error - case <-pc.abort: - select { - case result := <-pc.callback: - return result.Data, result.Error - default: - return nil, errors.New("Connection closed") + 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 { @@ -372,7 +393,7 @@ func newProtocolCallback(noReply bool, abort <-chan struct{}) *protocolCallback } } return &protocolCallback{ - callback: make(chan result, 1), - abort: abort, + done: make(chan struct{}), + abort: abort, } } diff --git a/event_emitter.go b/event_emitter.go index 102f715..d4d62ef 100644 --- a/event_emitter.go +++ b/event_emitter.go @@ -13,6 +13,7 @@ type EventEmitter interface { On(name string, handler interface{}) Once(name string, handler interface{}) RemoveListener(name string, handler interface{}) + RemoveListeners(name string) } type ( @@ -31,6 +32,10 @@ type ( } ) +func NewEventEmitter() EventEmitter { + return &eventEmitter{} +} + func (e *eventEmitter) Emit(name string, payload ...interface{}) (hasListener bool) { e.eventsMutex.Lock() e.init() @@ -64,6 +69,13 @@ func (e *eventEmitter) RemoveListener(name string, handler interface{}) { } } +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() diff --git a/fetch.go b/fetch.go index 89ca518..fc7f79f 100644 --- a/fetch.go +++ b/fetch.go @@ -334,7 +334,7 @@ func (r *apiResponseImpl) Body() ([]byte, error) { } return nil, err } - body := result.(map[string]interface{})["binary"] + body := result["binary"] if body == nil { return nil, errors.New("response has been disposed") } diff --git a/generated-interfaces.go b/generated-interfaces.go index 6354f1c..17b8071 100644 --- a/generated-interfaces.go +++ b/generated-interfaces.go @@ -312,10 +312,10 @@ type BrowserContext interface { // URLs are returned. Cookies(urls ...string) ([]Cookie, error) - // The method adds a function called “name” on the `window` object of every frame in every page in the context. When - // called, the function executes “callback” and returns a [Promise] which resolves to the return value of “callback”. - // If the “callback” returns a [Promise], it will be awaited. - // The first argument of the “callback” function contains information about the caller: `{ browserContext: + // 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. // @@ -323,9 +323,10 @@ type BrowserContext interface { // 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 “name” on the `window` object of every frame in every page in the context. When - // called, the function executes “callback” and returns a [Promise] which resolves to the return value of “callback”. - // If the “callback” returns a [Promise], it will be awaited. + // 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. @@ -374,10 +375,10 @@ type BrowserContext interface { // 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 “Browser.newContext.serviceWorkers” to `block`. + // using request interception by setting “[object Object]” to `block`. // - // 1. url: A glob pattern, regex pattern or predicate receiving [URL] to match while routing. When a “baseURL” via the context - // options was provided and the passed URL is a path, it gets merged via the + // 1. url: A glob pattern, regex pattern or predicate receiving [URL] to match while routing. 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. // 2. handler: handler function to route the request. // @@ -388,7 +389,7 @@ type BrowserContext interface { // [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 “Browser.newContext.serviceWorkers” to `block`. + // 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. @@ -414,7 +415,7 @@ type BrowserContext interface { // timeout: Maximum navigation time in milliseconds SetDefaultNavigationTimeout(timeout float64) - // This setting will change the default maximum time for all the methods accepting “timeout” option. + // 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]. // @@ -444,8 +445,8 @@ type BrowserContext interface { // Removes all routes created with [BrowserContext.Route] and [BrowserContext.RouteFromHAR]. UnrouteAll(options ...BrowserContextUnrouteAllOptions) error - // Removes a route created with [BrowserContext.Route]. When “handler” is not specified, removes all routes for the - // “url”. + // 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]. @@ -507,8 +508,8 @@ type BrowserType interface { Launch(options ...BrowserTypeLaunchOptions) (Browser, error) // Returns the persistent browser context instance. - // Launches browser that uses persistent storage located at “userDataDir” and returns the only context. Closing this - // context will automatically close the browser. + // 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. More details for // [Chromium](https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md#introduction) and @@ -729,13 +730,13 @@ type ElementHandle interface { // 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 “force” option is set. + // 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 “timeout”, this method throws a [TimeoutError]. - // Passing zero timeout disables this. + // 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]. // @@ -744,13 +745,13 @@ type ElementHandle interface { Check(options ...ElementHandleCheckOptions) error // This method clicks the element by performing the following steps: - // 1. Wait for [actionability] checks on the element, unless “force” option is set. + // 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 “position”. - // 4. Wait for initiated navigations to either succeed or fail, unless “noWaitAfter” option is set. + // 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 “timeout”, this method throws a [TimeoutError]. - // Passing zero timeout disables this. + // 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]. // @@ -762,12 +763,12 @@ type ElementHandle interface { ContentFrame() (Frame, error) // This method double clicks the element by performing the following steps: - // 1. Wait for [actionability] checks on the element, unless “force” option is set. + // 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 “position”. + // 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 “timeout”, this method throws a [TimeoutError]. - // Passing zero timeout disables this. + // 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]. @@ -799,32 +800,32 @@ type ElementHandle interface { // [locators]: https://playwright.dev/docs/locators DispatchEvent(typ string, eventInit ...interface{}) error - // Returns the return value of “expression”. + // 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 “expression”. If no elements match the selector, the method throws an error. - // If “expression” returns a [Promise], then [ElementHandle.EvalOnSelector] would wait for the promise to resolve and - // return its value. + // 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 “expression”. + // 3. arg: Optional argument to pass to “[object Object]”. EvalOnSelector(selector string, expression string, arg ...interface{}) (interface{}, error) - // Returns the return value of “expression”. + // 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 “expression”. - // If “expression” returns a [Promise], then [ElementHandle.EvalOnSelectorAll] would wait for the promise to resolve - // and return its value. + // 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 “expression”. + // 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 @@ -862,12 +863,12 @@ type ElementHandle interface { 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 “force” option is set. + // 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 “position”. + // 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 “timeout”, this method throws a [TimeoutError]. - // Passing zero timeout disables this. + // 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]. // @@ -951,18 +952,18 @@ type ElementHandle interface { OwnerFrame() (Frame, error) // Focuses the element, and then uses [Keyboard.Down] and [Keyboard.Up]. - // “key” can specify the intended + // “[object Object]” can specify the intended // [keyboardEvent.Key] value or a single character - // to generate the text for. A superset of the “key” values can be found + // 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 “key” in the upper case. - // If “key” is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective - // texts. + // 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. // @@ -1056,13 +1057,13 @@ type ElementHandle interface { // 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 “force” option is set. If - // the element is detached during the checks, the whole action is retried. + // 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 “timeout”, this method throws a [TimeoutError]. - // Passing zero timeout disables this. + // 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]. // @@ -1088,12 +1089,12 @@ type ElementHandle interface { 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 “force” option is set. + // 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 “position”. + // 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 “timeout”, this method throws a [TimeoutError]. - // Passing zero timeout disables this. + // 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]. @@ -1121,13 +1122,13 @@ type ElementHandle interface { // 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 “force” option is set. + // 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 “timeout”, this method throws a [TimeoutError]. - // Passing zero timeout disables this. + // 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]. // @@ -1135,9 +1136,10 @@ type ElementHandle interface { // [locators]: https://playwright.dev/docs/locators Uncheck(options ...ElementHandleUncheckOptions) error - // Returns when the element satisfies the “state”. - // Depending on the “state” 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. + // 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. @@ -1146,7 +1148,7 @@ type ElementHandle interface { // - `"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 “timeout” milliseconds, this method will throw. + // 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. // @@ -1160,12 +1162,12 @@ type ElementHandle interface { // [editable]: https://playwright.dev/docs/actionability#editable WaitForElementState(state ElementState, options ...ElementHandleWaitForElementStateOptions) error - // Returns element specified by selector when it satisfies “state” option. Returns `null` if waiting for `hidden` or - // `detached`. - // Wait for the “selector” relative to the element handle to satisfy “state” option (either appear/disappear from dom, - // or become visible/hidden). If at the moment of calling the method “selector” already satisfies the condition, the - // method will return immediately. If the selector doesn't satisfy the condition for the “timeout” milliseconds, the - // function will throw. + // 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. // @@ -1209,17 +1211,18 @@ type Frame interface { // content. AddStyleTag(options FrameAddStyleTagOptions) (ElementHandle, error) - // This method checks an element matching “selector” by performing the following steps: - // 1. Find an element matching “selector”. If there is none, wait until a matching element is attached to the DOM. + // 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 “force” option is set. If - // the element is detached during the checks, the whole action is retried. + // 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 “timeout”, this method throws a [TimeoutError]. - // Passing zero timeout disables this. + // 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]. // @@ -1232,15 +1235,16 @@ type Frame interface { ChildFrames() []Frame - // This method clicks an element matching “selector” by performing the following steps: - // 1. Find an element matching “selector”. If there is none, wait until a matching element is attached to the DOM. - // 2. Wait for [actionability] checks on the matched element, unless “force” option is set. If - // the element is detached during the checks, the whole action is retried. + // 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 “position”. - // 5. Wait for initiated navigations to either succeed or fail, unless “noWaitAfter” option is set. - // When all steps combined have not finished during the specified “timeout”, this method throws a [TimeoutError]. - // Passing zero timeout disables this. + // 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]. // @@ -1254,15 +1258,16 @@ type Frame interface { // Gets the full HTML contents of the frame, including the doctype. Content() (string, error) - // This method double clicks an element matching “selector” by performing the following steps: - // 1. Find an element matching “selector”. If there is none, wait until a matching element is attached to the DOM. - // 2. Wait for [actionability] checks on the matched element, unless “force” option is set. If - // the element is detached during the checks, the whole action is retried. + // 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 “position”. 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 “timeout”, this method throws a [TimeoutError]. - // Passing zero timeout disables this. + // 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]. @@ -1306,24 +1311,24 @@ type Frame interface { // will be used. DragAndDrop(source string, target string, options ...FrameDragAndDropOptions) error - // Returns the return value of “expression”. + // 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 - // “expression”. If no elements match the selector, the method throws an error. - // If “expression” returns a [Promise], then [Frame.EvalOnSelector] would wait for the promise to resolve and return - // its value. + // “[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 “expression”. + // 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 “expression”. + // 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 “expression”. - // If “expression” returns a [Promise], then [Frame.EvalOnSelectorAll] would wait for the promise to resolve and + // 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. @@ -1331,10 +1336,10 @@ type Frame interface { // 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 “expression”. + // 3. arg: Optional argument to pass to “[object Object]”. EvalOnSelectorAll(selector string, expression string, arg ...interface{}) (interface{}, error) - // Returns the return value of “expression”. + // 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 @@ -1343,10 +1348,10 @@ type Frame interface { // // 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 “expression”. + // 2. arg: Optional argument to pass to “[object Object]”. Evaluate(expression string, arg ...interface{}) (interface{}, error) - // Returns the return value of “expression” as a [JSHandle]. + // 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 @@ -1354,10 +1359,10 @@ type Frame interface { // // 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 “expression”. + // 2. arg: Optional argument to pass to “[object Object]”. EvaluateHandle(expression string, arg ...interface{}) (JSHandle, error) - // This method waits for an element matching “selector”, waits for [actionability] checks, + // 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 ``, `