From b0749e3a6dddc9ba5348386140b3584c8f8db7d9 Mon Sep 17 00:00:00 2001 From: Joel Einbinder Date: Wed, 18 Mar 2020 16:23:25 -0700 Subject: [PATCH] fix(docs): fixup and lint optionals and return values in api.md (#1376) Currently in our API `?` means null, but sometimes it means optional. Linting optional/nulls with this patch is required for #1166 to land nicely. Previously, return types were not being linted in `api.md`. This is fixed, along with many broken return types. This patch considers `?` to mean nullable, and has some heuristics to determine optionality. I believe this to be the minimal patch needed to unblock #1166. After it lands, we can consider changing the api docs to hopefully remove some heuristics and strangeness. --- docs/api.md | 154 +++++++++--------- src/accessibility.ts | 2 +- src/dom.ts | 2 +- src/server/browserServer.ts | 9 +- utils/doclint/check_public_api/JSBuilder.js | 8 +- utils/doclint/check_public_api/MDBuilder.js | 21 ++- utils/doclint/check_public_api/index.js | 45 +++-- .../test/check-nullish/api.ts | 19 +++ .../test/check-nullish/doc.md | 32 ++++ .../test/check-nullish/result.txt | 0 .../test/check-returns/api.ts | 5 +- utils/doclint/check_public_api/test/test.js | 1 + 12 files changed, 188 insertions(+), 110 deletions(-) create mode 100644 utils/doclint/check_public_api/test/check-nullish/api.ts create mode 100644 utils/doclint/check_public_api/test/check-nullish/doc.md create mode 100644 utils/doclint/check_public_api/test/check-nullish/result.txt diff --git a/docs/api.md b/docs/api.md index 972ddb67c75f2..810583542062d 100644 --- a/docs/api.md +++ b/docs/api.md @@ -194,7 +194,7 @@ Indicates that the browser is connected. - `options` <[Object]> - `ignoreHTTPSErrors` <[boolean]> Whether to ignore HTTPS errors during navigation. Defaults to `false`. - `bypassCSP` <[boolean]> Toggles bypassing page's Content-Security-Policy. - - `viewport` <[Object]> Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `null` disables the default viewport. + - `viewport` Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `null` disables the default viewport. - `width` <[number]> page width in pixels. - `height` <[number]> page height in pixels. - `userAgent` <[string]> Specific user agent to use in this context. @@ -202,12 +202,12 @@ Indicates that the browser is connected. - `isMobile` <[boolean]> Whether the `meta viewport` tag is taken into account and touch events are enabled. Defaults to `false`. Not supported in Firefox. - `hasTouch` <[boolean]> Specifies if viewport supports touch events. Defaults to false. - `javaScriptEnabled` <[boolean]> Whether or not to enable or disable JavaScript in the context. Defaults to true. - - `timezoneId` Changes the timezone of the context. See [ICU’s `metaZones.txt`](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1) for a list of supported timezone IDs. + - `timezoneId` <[string]> Changes the timezone of the context. See [ICU’s `metaZones.txt`](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1) for a list of supported timezone IDs. - `geolocation` <[Object]> - `latitude` <[number]> Latitude between -90 and 90. - `longitude` <[number]> Longitude between -180 and 180. - - `accuracy` <[number]> Optional non-negative accuracy value. - - `locale` 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. + - `accuracy` <[number]> Non-negative accuracy value. Defaults to `0`. + - `locale` <[string]> 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. - `permissions` <[Array]<[string]>> A list of permissions to grant to all pages in this context. See [browserContext.grantPermissions](#browsercontextgrantpermissionspermissions-options) for more details. - `extraHTTPHeaders` <[Object]> An object containing additional HTTP headers to be sent with every request. All header values must be strings. - `offline` <[boolean]> Whether to emulate network being offline. Defaults to `false`. @@ -231,22 +231,22 @@ Creates a new browser context. It won't share cookies/cache with other browser c #### browser.newPage([options]) - `options` <[Object]> - - `ignoreHTTPSErrors` Whether to ignore HTTPS errors during navigation. Defaults to `false`. - - `bypassCSP` Toggles bypassing page's Content-Security-Policy. - - `viewport` <[Object]> Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `null` disables the default viewport. + - `ignoreHTTPSErrors` <[boolean]> Whether to ignore HTTPS errors during navigation. Defaults to `false`. + - `bypassCSP` <[boolean]> Toggles bypassing page's Content-Security-Policy. + - `viewport` Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `null` disables the default viewport. - `width` <[number]> page width in pixels. - `height` <[number]> page height in pixels. - `userAgent` <[string]> Specific user agent to use in this context. - `deviceScaleFactor` <[number]> Specify device scale factor (can be thought of as dpr). Defaults to `1`. - `isMobile` <[boolean]> Whether the `meta viewport` tag is taken into account and touch events are enabled. Defaults to `false`. Not supported in Firefox. - `hasTouch` <[boolean]> Specifies if viewport supports touch events. Defaults to false. - - `javaScriptEnabled` Whether or not to enable or disable JavaScript in the context. Defaults to true. - - `timezoneId` Changes the timezone of the context. See [ICU’s `metaZones.txt`](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1) for a list of supported timezone IDs. + - `javaScriptEnabled` <[boolean]> Whether or not to enable or disable JavaScript in the context. Defaults to `true`. + - `timezoneId` <[string]> Changes the timezone of the context. See [ICU’s `metaZones.txt`](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1) for a list of supported timezone IDs. - `geolocation` <[Object]> - `latitude` <[number]> Latitude between -90 and 90. - `longitude` <[number]> Longitude between -180 and 180. - - `accuracy` <[number]> Optional non-negative accuracy value. - - `locale` 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. + - `accuracy` <[number]> Non-negative accuracy value. Defaults to `0`. + - `locale` <[string]> 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. - `permissions` <[Array]<[string]>> A list of permissions to grant to all pages in this context. See [browserContext.grantPermissions](#browsercontextgrantpermissionspermissions-options) for more details. - `extraHTTPHeaders` <[Object]> An object containing additional HTTP headers to be sent with every request. All header values must be strings. - `offline` <[boolean]> Whether to emulate network being offline. Defaults to `false`. @@ -329,9 +329,9 @@ const newPage = await event.page(); - `cookies` <[Array]<[Object]>> - `name` <[string]> **required** - `value` <[string]> **required** - - `url` <[string]> either url or domain / path are **required** - - `domain` <[string]> either url or domain / path are **required** - - `path` <[string]> either url or domain / path are **required** + - `url` <[string]> either url or domain / path are required + - `domain` <[string]> either url or domain / path are required + - `path` <[string]> either url or domain / path are required - `expires` <[number]> Unix time in seconds. - `httpOnly` <[boolean]> - `secure` <[boolean]> @@ -403,7 +403,6 @@ will be closed. - `domain` <[string]> - `path` <[string]> - `expires` <[number]> Unix time in seconds. - - `size` <[number]> - `httpOnly` <[boolean]> - `secure` <[boolean]> - `sameSite` <"Strict"|"Lax"|"None"> @@ -542,13 +541,13 @@ The extra HTTP headers will be sent with every request initiated by any page in > **NOTE** `browserContext.setExtraHTTPHeaders` does not guarantee the order of headers in the outgoing requests. #### browserContext.setGeolocation(geolocation) -- `geolocation` <[Object]> - - `latitude` <[number]> Latitude between -90 and 90. - - `longitude` <[number]> Longitude between -180 and 180. - - `accuracy` <[number]> Optional non-negative accuracy value. +- `geolocation` + - `latitude` <[number]> Latitude between -90 and 90. **required** + - `longitude` <[number]> Longitude between -180 and 180. **required** + - `accuracy` <[number]> Non-negative accuracy value. Defaults to `0`. - returns: <[Promise]> -Sets the contexts's geolocation. Passing null or undefined emulates position unavailable. +Sets the contexts's geolocation. Passing `null` or `undefined` emulates position unavailable. ```js await browserContext.setGeolocation({latitude: 59.95, longitude: 30.31667}); @@ -558,8 +557,8 @@ await browserContext.setGeolocation({latitude: 59.95, longitude: 30.31667}); #### browserContext.setHTTPCredentials(httpCredentials) - `httpCredentials` - - `username` <[string]> - - `password` <[string]> + - `username` <[string]> **required** + - `password` <[string]> **required** - returns: <[Promise]> Provide credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication). @@ -575,7 +574,7 @@ To disable authentication, pass `null`. - `optionsOrPredicate` <[Function]|[Object]> Either a predicate that receives an event or an options object. - `predicate` <[Function]> receives the event data and resolves to truthy value when the waiting should resolve. - `timeout` <[number]> 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)](#browsercontextsetdefaulttimeouttimeout). -- returns: <[Promise]<[any]>> Promise which resolves to the event data value. +- returns: <[Promise]<[Object]>> Promise which resolves to the event data value. Waits for event to fire and passes its value into the predicate function. Resolves when the predicate returns truthy value. Will throw an error if the context closes before the event is fired. @@ -1219,7 +1218,7 @@ Shortcut for [page.mainFrame().focus(selector)](#framefocusselector-options). - `options` <[string]|[Object]> Frame name or other frame lookup options. - `name` <[string]> frame name specified in the `iframe`'s `name` attribute - `url` <[string]|[RegExp]|[Function]> A glob pattern, regex pattern or predicate receiving frame's `url` as a [URL] object. -- returns: <[Frame]> frame matching the criteria. +- returns: frame matching the criteria. Returns `null` if no frame matches. ```js const frame = page.frame('frame-name'); @@ -1349,10 +1348,10 @@ Page is guaranteed to have a main frame which persists during navigations. - `width` <[string]|[number]> Paper width, accepts values labeled with units. - `height` <[string]|[number]> Paper height, accepts values labeled with units. - `margin` <[Object]> Paper margins, defaults to none. - - `top` <[string]|[number]> Top margin, accepts values labeled with units. - - `right` <[string]|[number]> Right margin, accepts values labeled with units. - - `bottom` <[string]|[number]> Bottom margin, accepts values labeled with units. - - `left` <[string]|[number]> Left margin, accepts values labeled with units. + - `top` <[string]|[number]> Top margin, accepts values labeled with units. Defaults to `0`. + - `right` <[string]|[number]> Right margin, accepts values labeled with units. Defaults to `0`. + - `bottom` <[string]|[number]> Bottom margin, accepts values labeled with units. Defaults to `0`. + - `left` <[string]|[number]> Left margin, accepts values labeled with units. Defaults to `0`. - `preferCSSPageSize` <[boolean]> Give any CSS `@page` size declared in the page priority over what is declared in `width` and `height` or `format` options. Defaults to `false`, which will scale the content to fit the paper size. - returns: <[Promise]<[Buffer]>> Promise which resolves with PDF buffer. @@ -1426,7 +1425,7 @@ If `key` is a single character and no modifier keys besides `Shift` are being he - `'load'` - consider navigation to be finished when the `load` event is fired. - `'networkidle0'` - consider navigation to be finished when there are no more than 0 network connections for at least `500` ms. - `'networkidle2'` - consider navigation to be finished when there are no more than 2 network connections for at least `500` ms. -- returns: <[Promise]<[Response]>> Promise which resolves to the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect. +- returns: <[Promise]> Promise which resolves to the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect. #### page.route(url, handler) - `url` <[string]|[RegExp]|[function]\([string]\):[boolean]> A glob pattern, regex pattern or predicate receiving [URL] to match while routing. @@ -1640,7 +1639,7 @@ This is a shortcut for [page.mainFrame().url()](#frameurl) - `'mutation'` - to execute `pageFunction` on every DOM mutation. - `timeout` <[number]> 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)](#browsercontextsetdefaulttimeouttimeout) or [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) methods. - `...args` <...[Serializable]|[JSHandle]> Arguments to pass to `pageFunction` -- returns: <[Promise]<[JSHandle]>> Promise which resolves to a JSHandle of the success value +- returns: <[Promise]> Promise which resolves to a JSHandle of the success value This method behaves differently with respect to the type of the first parameter: - if `selectorOrFunctionOrTimeout` is a `string`, then the first argument is treated as a [selector] and the method is a shortcut for [page.waitForSelector](#pagewaitforselectorselector-options) @@ -1671,7 +1670,7 @@ Shortcut for [page.mainFrame().waitFor(selectorOrFunctionOrTimeout[, options[, . - `optionsOrPredicate` <[Function]|[Object]> Either a predicate that receives an event or an options object. - `predicate` <[Function]> receives the event data and resolves to truthy value when the waiting should resolve. - `timeout` <[number]> 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)](#browsercontextsetdefaulttimeouttimeout) or [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) methods. -- returns: <[Promise]<[any]>> Promise which resolves to the event data value. +- returns: <[Promise]<[Object]>> Promise which resolves to the event data value. Waits for event to fire and passes its value into the predicate function. Resolves when the predicate returns truthy value. Will throw an error if the page is closed before the event is fired. @@ -1755,7 +1754,7 @@ const [response] = await Promise.all([ Shortcut for [page.mainFrame().waitForNavigation(options)](#framewaitfornavigationoptions). #### page.waitForRequest(urlOrPredicate[, options]) -- `urlOrPredicate` Optional. Request URL string, regex or predicate receiving [Request] object. +- `urlOrPredicate` <[string]|[RegExp]|[Function]> Request URL string, regex or predicate receiving [Request] object. - `options` <[Object]> Optional waiting parameters - `timeout` <[number]> 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(timeout)](#pagesetdefaulttimeouttimeout) method. - returns: <[Promise]<[Request]>> Promise which resolves to the matched request. @@ -1771,7 +1770,7 @@ await page.waitForRequest(request => request.url().searchParams.get('foo') === ' ``` #### page.waitForResponse(urlOrPredicate[, options]) -- `urlOrPredicate` Optional. Request URL string, regex or predicate receiving [Response] object. +- `urlOrPredicate` <[string]|[RegExp]|[Function]> Request URL string, regex or predicate receiving [Response] object. - `options` <[Object]> Optional waiting parameters - `timeout` <[number]> 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(timeout)](#browsercontextsetdefaulttimeouttimeout) or [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) methods. - returns: <[Promise]<[Response]>> Promise which resolves to the matched response. @@ -2346,7 +2345,7 @@ Returns frame's url. - `'mutation'` - to execute `pageFunction` on every DOM mutation. - `timeout` <[number]> 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)](#browsercontextsetdefaulttimeouttimeout) or [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) methods. - `...args` <...[Serializable]|[JSHandle]> Arguments to pass to `pageFunction` -- returns: <[Promise]<[JSHandle]>> Promise which resolves to a JSHandle of the success value +- returns: <[Promise]> Promise which resolves to a JSHandle of the success value This method behaves differently with respect to the type of the first parameter: - if `selectorOrFunctionOrTimeout` is a `string`, then the first argument is treated as a [selector] and the method is a shortcut for [frame.waitForSelector](#framewaitforselectororfunctionortimeout-options-args) @@ -2629,7 +2628,7 @@ This method scrolls element into view if needed, and then uses [page.mouse](#pag If the element is detached from DOM, the method throws an error. #### elementHandle.contentFrame() -- returns: <[Promise]> Resolves to the content frame for element handles referencing iframe nodes, or null otherwise +- returns: <[Promise]> Resolves to the content frame for element handles referencing iframe nodes, or `null` otherwise #### elementHandle.dblclick([options]) - `options` <[Object]> @@ -2698,7 +2697,7 @@ This method scrolls element into view if needed, and then uses [page.mouse](#pag If the element is detached from DOM, the method throws an error. #### elementHandle.ownerFrame() -- returns: <[Promise]<[Frame]>> Returns the frame containing the given element. +- returns: <[Promise]> Returns the frame containing the given element. #### elementHandle.press(key[, options]) - `key` <[string]> Name of key to press, such as `ArrowLeft`. See [USKeyboardLayout] for a list of all key names. @@ -2725,7 +2724,7 @@ If `key` is a single character and no modifier keys besides `Shift` are being he - `type` <"png"|"jpeg"> Specify screenshot type, defaults to `png`. - `quality` <[number]> The quality of the image, between 0-100. Not applicable to `png` images. - `omitBackground` <[boolean]> Hides default white background and allows capturing screenshots with transparency. Not applicable to `jpeg` images. Defaults to `false`. -- returns: <[Promise]<|[Buffer]>> Promise which resolves to buffer with the captured screenshot. +- returns: <[Promise]<[Buffer]>> Promise which resolves to buffer with the captured screenshot. This method scrolls element into view if needed before taking a screenshot. If the element is detached from DOM, the method throws an error. @@ -2772,9 +2771,9 @@ handle.selectOption({ value: 'blue' }, { index: 2 }, 'red'); #### elementHandle.setInputFiles(files) - `files` <[string]|[Array]<[string]>|[Object]|[Array]<[Object]>> - - `name` <[string]> <[File]> name - - `type` <[string]> <[File]> type - - `data` <[string]> Base64-encoded data + - `name` <[string]> [File] name **required** + - `type` <[string]> [File] type **required** + - `data` <[string]> Base64-encoded data **required** - returns: <[Promise]> This method expects `elementHandle` to point to an [input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). @@ -2936,9 +2935,9 @@ function, it **will not be called**. #### consoleMessage.location() - returns: <[Object]> - - `url` <[string]> URL of the resource if known or `undefined` otherwise. - - `lineNumber` <[number]> 0-based line number in the resource if known or `undefined` otherwise. - - `columnNumber` <[number]> 0-based column number in the resource if known or `undefined` otherwise. + - `url` <[string]> URL of the resource if available. + - `lineNumber` <[number]> 0-based line number in the resource if available. + - `columnNumber` <[number]> 0-based column number in the resource if available. #### consoleMessage.text() - returns: <[string]> @@ -3254,7 +3253,7 @@ 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`. #### request.response() -- returns: <[Promise] A matching [Response] object, or `null` if the response was not received due to error. +- returns: <[Promise]> A matching [Response] object, or `null` if the response was not received due to error. #### request.url() - returns: <[string]> URL of the request. @@ -3281,7 +3280,7 @@ ResourceType will be one of the following: `document`, `stylesheet`, `image`, `m - returns: > Promise which resolves to a buffer with response body. #### response.finished() -- returns: > Waits for this response to finish, returns failure error if request failed. +- returns: <[Promise]> Waits for this response to finish, returns failure error if request failed. #### response.frame() - returns: <[Frame]> A [Frame] that initiated this response. @@ -3290,7 +3289,7 @@ ResourceType will be one of the following: `document`, `stylesheet`, `image`, `m - returns: <[Object]> An object with HTTP headers associated with the response. All header names are lower-case. #### response.json() -- returns: > Promise which resolves to a JSON representation of response body. +- returns: <[Promise]<[Object]>> Promise which resolves to a JSON representation of response body. This method will throw if the response body is not parsable via `JSON.parse`. @@ -3489,33 +3488,33 @@ Most of the accessibility tree gets filtered out when converting from Blink AX T - `options` <[Object]> - `interestingOnly` <[boolean]> Prune uninteresting nodes from the tree. Defaults to `true`. - `root` <[ElementHandle]> The root DOM element for the snapshot. Defaults to the whole page. -- returns: <[Promise]<[Object]>> An [AXNode] object with the following properties: +- returns: <[Promise]> An [AXNode] object with the following properties: - `role` <[string]> The [role](https://www.w3.org/TR/wai-aria/#usage_intro). - `name` <[string]> A human readable name for the node. - - `value` <[string]|[number]> The current value of the node. - - `description` <[string]> An additional human readable description of the node. - - `keyshortcuts` <[string]> Keyboard shortcuts associated with this node. - - `roledescription` <[string]> A human readable alternative to the role. - - `valuetext` <[string]> A description of the current value. - - `disabled` <[boolean]> Whether the node is disabled. - - `expanded` <[boolean]> Whether the node is expanded or collapsed. - - `focused` <[boolean]> Whether the node is focused. - - `modal` <[boolean]> Whether the node is [modal](https://en.wikipedia.org/wiki/Modal_window). - - `multiline` <[boolean]> Whether the node text input supports multiline. - - `multiselectable` <[boolean]> Whether more than one child can be selected. - - `readonly` <[boolean]> Whether the node is read only. - - `required` <[boolean]> Whether the node is required. - - `selected` <[boolean]> Whether the node is selected in its parent node. - - `checked` <[boolean]|"mixed"> Whether the checkbox is checked, or "mixed". - - `pressed` <[boolean]|"mixed"> Whether the toggle button is checked, or "mixed". - - `level` <[number]> The level of a heading. - - `valuemin` <[number]> The minimum value in a node. - - `valuemax` <[number]> The maximum value in a node. - - `autocomplete` <[string]> What kind of autocomplete is supported by a control. - - `haspopup` <[string]> What kind of popup is currently being shown for a node. - - `invalid` <[string]> Whether and in what way this node's value is invalid. - - `orientation` <[string]> Whether the node is oriented horizontally or vertically. - - `children` <[Array]<[Object]>> Child [AXNode]s of this node, if any. + - `value` <[string]|[number]> The current value of the node, if applicable. + - `description` <[string]> An additional human readable description of the node, if applicable. + - `keyshortcuts` <[string]> Keyboard shortcuts associated with this node, if applicable. + - `roledescription` <[string]> A human readable alternative to the role, if applicable. + - `valuetext` <[string]> A description of the current value, if applicable. + - `disabled` <[boolean]> Whether the node is disabled, if applicable. + - `expanded` <[boolean]> Whether the node is expanded or collapsed, if applicable. + - `focused` <[boolean]> Whether the node is focused, if applicable. + - `modal` <[boolean]> Whether the node is [modal](https://en.wikipedia.org/wiki/Modal_window), if applicable. + - `multiline` <[boolean]> Whether the node text input supports multiline, if applicable. + - `multiselectable` <[boolean]> Whether more than one child can be selected, if applicable. + - `readonly` <[boolean]> Whether the node is read only, if applicable. + - `required` <[boolean]> Whether the node is required, if applicable. + - `selected` <[boolean]> Whether the node is selected in its parent node, if applicable. + - `checked` <[boolean]|"mixed"> Whether the checkbox is checked, or "mixed", if applicable. + - `pressed` <[boolean]|"mixed"> Whether the toggle button is checked, or "mixed", if applicable. + - `level` <[number]> The level of a heading, if applicable. + - `valuemin` <[number]> The minimum value in a node, if applicable. + - `valuemax` <[number]> The maximum value in a node, if applicable. + - `autocomplete` <[string]> What kind of autocomplete is supported by a control, if applicable. + - `haspopup` <[string]> What kind of popup is currently being shown for a node, if applicable. + - `invalid` <[string]> Whether and in what way this node's value is invalid, if applicable. + - `orientation` <[string]> Whether the node is oriented horizontally or vertically, if applicable. + - `children` <[Array]<[Object]>> Child [AXNode]s of this node, if any, if applicable. Captures the current state of the accessibility tree. The returned object represents the root accessible node of the page. @@ -3656,8 +3655,8 @@ const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. #### browserType.connect(options) - `options` <[Object]> - - `wsEndpoint` <[string]> A browser websocket endpoint to connect to. - - `slowMo` Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on. Defaults to 0. + - `wsEndpoint` <[string]> A browser websocket endpoint to connect to. **required** + - `slowMo` <[number]> Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on. Defaults to 0. - returns: <[Promise]<[Browser]>> This methods attaches Playwright to an existing browser instance. @@ -3910,7 +3909,7 @@ const v8toIstanbul = require('v8-to-istanbul'); #### chromiumCoverage.stopCSSCoverage() - returns: <[Promise]<[Array]<[Object]>>> Promise that resolves to the array of coverage reports for all stylesheets - `url` <[string]> StyleSheet URL - - `text` <[string]> StyleSheet content + - `text` <[string]> StyleSheet content, if available. - `ranges` <[Array]<[Object]>> StyleSheet ranges that were used. Ranges are sorted and non-overlapping. - `start` <[number]> A start offset in text, inclusive - `end` <[number]> An end offset in text, exclusive @@ -3920,8 +3919,13 @@ const v8toIstanbul = require('v8-to-istanbul'); #### chromiumCoverage.stopJSCoverage() - returns: <[Promise]<[Array]<[Object]>>> Promise that resolves to the array of coverage reports for all scripts - `url` <[string]> Script URL - - `source` <[string]> Script content + - `source` <[string]> Script content, if applicable. - `functions` <[Array]<[Object]>> V8-specific coverage format. + - `functionName` <[string]> + - `ranges` <[Array]<[Object]>> + - `count` <[number]> + - `startOffset` <[number]> + - `endOffset` <[number]> > **NOTE** JavaScript Coverage doesn't include anonymous scripts by default. However, scripts with sourceURLs are reported. diff --git a/src/accessibility.ts b/src/accessibility.ts index 63324b46d11f7..7edfc99f8833e 100644 --- a/src/accessibility.ts +++ b/src/accessibility.ts @@ -66,7 +66,7 @@ export class Accessibility { async snapshot(options: { interestingOnly?: boolean; - root?: dom.ElementHandle | null; + root?: dom.ElementHandle; } = {}): Promise { const { interestingOnly = true, diff --git a/src/dom.ts b/src/dom.ts index bb818416f62b4..83164bbef5309 100644 --- a/src/dom.ts +++ b/src/dom.ts @@ -383,7 +383,7 @@ export class ElementHandle extends js.JSHandle { return this._page._delegate.getBoundingBox(this); } - async screenshot(options?: types.ElementScreenshotOptions): Promise { + async screenshot(options?: types.ElementScreenshotOptions): Promise { return this._page._screenshotter.screenshotElement(this, options); } diff --git a/src/server/browserServer.ts b/src/server/browserServer.ts index b75113a074c3d..feb813b2739d0 100644 --- a/src/server/browserServer.ts +++ b/src/server/browserServer.ts @@ -20,20 +20,21 @@ import * as platform from '../platform'; export class BrowserServer extends platform.EventEmitter { private _process: ChildProcess; private _gracefullyClose: () => Promise; - private _browserWSEndpoint: string | null = null; + private _browserWSEndpoint: string = ''; - constructor(process: ChildProcess, gracefullyClose: () => Promise, wsEndpoint: string | null) { + constructor(process: ChildProcess, gracefullyClose: () => Promise, wsEndpoint: string|null) { super(); this._process = process; this._gracefullyClose = gracefullyClose; - this._browserWSEndpoint = wsEndpoint; + if (wsEndpoint) + this._browserWSEndpoint = wsEndpoint; } process(): ChildProcess { return this._process; } - wsEndpoint(): string | null { + wsEndpoint(): string { return this._browserWSEndpoint; } diff --git a/utils/doclint/check_public_api/JSBuilder.js b/utils/doclint/check_public_api/JSBuilder.js index ec94d553f3d6e..2030923828da6 100644 --- a/utils/doclint/check_public_api/JSBuilder.js +++ b/utils/doclint/check_public_api/JSBuilder.js @@ -184,8 +184,8 @@ function checkSources(sources, externalDependencies) { /** * @param {!ts.Type} type */ - function isNotNullish(type) { - return !((type.flags & ts.TypeFlags.Undefined) || (type.flags & ts.TypeFlags.Null)); + function isNotUndefined(type) { + return !(type.flags & ts.TypeFlags.Undefined); } /** @@ -234,7 +234,7 @@ function checkSources(sources, externalDependencies) { } if (type.isUnion() && (typeName.includes('|') || type.types.every(type => type.isStringLiteral() || type.intrinsicName === 'number'))) { const types = type.types - .filter(isNotNullish) + .filter(isNotUndefined) .map(type => serializeType(type, circular)); const name = types.map(type => type.name).join('|'); const properties = [].concat(...types.map(type => type.properties)); @@ -298,7 +298,7 @@ function checkSources(sources, externalDependencies) { if (signatures.length) return signatures[0]; if (type.isUnion()) { - const innerTypes = type.types.filter(isNotNullish); + const innerTypes = type.types.filter(isNotUndefined); if (innerTypes.length === 1) return signatureForType(innerTypes[0]); } diff --git a/utils/doclint/check_public_api/MDBuilder.js b/utils/doclint/check_public_api/MDBuilder.js index 96da960499525..f736ccb910b21 100644 --- a/utils/doclint/check_public_api/MDBuilder.js +++ b/utils/doclint/check_public_api/MDBuilder.js @@ -47,8 +47,9 @@ class MDOutline { /** * @param {HTMLLIElement} element + * @param {boolean} defaultRequired */ - function parseProperty(element) { + function parseProperty(element, defaultRequired) { const clone = element.cloneNode(true); const ul = clone.querySelector(':scope > ul'); const str = parseComment(extractSiblingsIntoFragment(clone.firstChild, ul)); @@ -64,8 +65,16 @@ class MDOutline { const text = childElement.textContent; if (text.startsWith(`"`) || text.startsWith(`'`)) continue; - const property = parseProperty(childElement); - property.required = property.comment.includes('***required***'); + const property = parseProperty(childElement, true); + property.required = defaultRequired; + if (property.comment.toLowerCase().includes('defaults to ')) + property.required = false; + if (property.comment.toLowerCase().includes('if applicable.')) + property.required = false; + if (property.comment.toLowerCase().includes('if available.')) + property.required = false; + if (property.comment.includes('**required**')) + property.required = true; properties.push(property); } } @@ -151,13 +160,13 @@ class MDOutline { const ul = content.querySelector('ul'); for (const element of content.querySelectorAll('h4 + ul > li')) { if (element.matches('li') && element.textContent.trim().startsWith('<')) { - returnType = parseProperty(element); + returnType = parseProperty(element, false); } else if (element.matches('li') && element.firstChild.matches && element.firstChild.matches('code')) { - const property = parseProperty(element); + const property = parseProperty(element, false); property.required = !optionalparams.has(property.name) && !property.name.startsWith('...'); args.push(property); } else if (element.matches('li') && element.firstChild.nodeType === Element.TEXT_NODE && element.firstChild.textContent.toLowerCase().startsWith('return')) { - returnType = parseProperty(element); + returnType = parseProperty(element, true); const expectedText = 'returns: '; let actualText = element.firstChild.textContent; let angleIndex = actualText.indexOf('<'); diff --git a/utils/doclint/check_public_api/index.js b/utils/doclint/check_public_api/index.js index 28ff6f397d196..0b3be5a9d4c6d 100644 --- a/utils/doclint/check_public_api/index.js +++ b/utils/doclint/check_public_api/index.js @@ -130,7 +130,7 @@ function compareDocumentations(actual, expected) { errors.push(`Method ${className}.${methodName} has unneeded description of return type`); else errors.push(`Method ${className}.${methodName} is missing return type description`); - } else if (actualMethod.hasReturn) { + } else if (actualMethod.type) { checkType(`Method ${className}.${methodName} has the wrong return type: `, actualMethod.type, expectedMethod.type); } const actualArgs = Array.from(actualMethod.args.keys()); @@ -143,13 +143,6 @@ function compareDocumentations(actual, expected) { for (const arg of argsDiff.extra) text.push(`- Non-existing argument found: ${arg}`); errors.push(text.join('\n')); - } else { - for (const name of actualMethod.args.keys()) { - const actual = actualMethod.args.get(name); - const expected = expectedMethod.args.get(name); - if (actual.required !== expected.required) - errors.push(`${className}.${methodName}(): ${name} should be ${expected.required ? 'required' : 'optional'}`); - } } for (const arg of argsDiff.equal) @@ -182,7 +175,9 @@ function compareDocumentations(actual, expected) { * @param {!Documentation.Member} expected */ function checkProperty(source, actual, expected) { - checkType(source + ' ' + actual.name, actual.type, expected.type); + if (actual.required !== expected.required) + errors.push(`${source}: ${actual.name} should be ${expected.required ? 'required' : 'optional'}`); + checkType(source + '.' + actual.name, actual.type, expected.type); } /** @@ -196,23 +191,41 @@ function compareDocumentations(actual, expected) { return; if (expected.name === 'T' || expected.name.includes('[T]')) return; - // We don't have nullchecks on for TypeScript - const actualName = actual.name.replace(/[\? ]/g, '').replace(/ElementHandle\/g, 'ElementHandle'); - // TypeScript likes to add some spaces - const expectedName = expected.name.replace(/\ /g, '').replace(/ElementHandle\/g, 'ElementHandle'); + /** @type {Parameters[]} */ + const mdReplacers = [ + [/\ /g, ''], + // We shortcut ? to null| + [/\?/g, 'null|'], + ]; + const tsReplacers = [ + [/\ /g, ''], + [/ElementHandle\/g, 'ElementHandle'], + [/ElementHandle\/g, 'ElementHandle'], + [/ElementHandle\/g, 'ElementHandle'], + [/Handle\/g, 'JSHandle'], + [/JSHandle\/g, 'JSHandle'], + [/object/g, 'Object'], + [/Promise\/, 'Promise'] + ] + let actualName = actual.name; + for (const replacer of mdReplacers) + actualName = actualName.replace(...replacer); + let expectedName = expected.name; + for (const replacer of tsReplacers) + expectedName = expectedName.replace(...replacer); if (expectedName !== actualName) errors.push(`${source} ${actualName} != ${expectedName}`); if (actual.name === 'boolean' || actual.name === 'string') return; - const actualPropertiesMap = new Map(actual.properties.map(property => [property.name, property.type])); - const expectedPropertiesMap = new Map(expected.properties.map(property => [property.name, property.type])); + const actualPropertiesMap = new Map(actual.properties.map(property => [property.name, property])); + const expectedPropertiesMap = new Map(expected.properties.map(property => [property.name, property])); const propertiesDiff = diff(Array.from(actualPropertiesMap.keys()).sort(), Array.from(expectedPropertiesMap.keys()).sort()); for (const propertyName of propertiesDiff.extra) errors.push(`${source} has unexpected property '${propertyName}'`); for (const propertyName of propertiesDiff.missing) errors.push(`${source} is missing property ${propertyName}`); for (const propertyName of propertiesDiff.equal) - checkType(source + '.' + propertyName, actualPropertiesMap.get(propertyName), expectedPropertiesMap.get(propertyName)); + checkProperty(source, actualPropertiesMap.get(propertyName), expectedPropertiesMap.get(propertyName)); } return errors; diff --git a/utils/doclint/check_public_api/test/check-nullish/api.ts b/utils/doclint/check_public_api/test/check-nullish/api.ts new file mode 100644 index 0000000000000..a2b440d5f1186 --- /dev/null +++ b/utils/doclint/check_public_api/test/check-nullish/api.ts @@ -0,0 +1,19 @@ +class Foo { + bar(options: {x: number, y: number, maybe?: number, nullable: string|null, object?: {one: number, two?: number}}) { + + } + + async goBack() : Promise { + return null; + } + + response(): Response | null { + return null; + } + + baz(): {abc: number, def?: number, ghi: string} | null { + return null; + } +} + +export {Foo}; \ No newline at end of file diff --git a/utils/doclint/check_public_api/test/check-nullish/doc.md b/utils/doclint/check_public_api/test/check-nullish/doc.md new file mode 100644 index 0000000000000..e9e74259b594c --- /dev/null +++ b/utils/doclint/check_public_api/test/check-nullish/doc.md @@ -0,0 +1,32 @@ +### class: Foo + +#### foo.bar(options) +- `options` <[Object]> + - `x` <[number]> **required** + - `y` <[number]> **required** + - `nullable` **required** + - `maybe` <[number]> + - `object` <[Object]> + - `one` <[number]> + - `two` <[number]> defaults to `2`. + +#### foo.baz() +- returns: + - `abc` <[number]> + - `def` <[number]> if applicable. + - `ghi` <[string]> + + +#### foo.goBack() +- returns: <[Promise]> Promise which resolves to the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect. If +can not go back, resolves to `null`. + +#### foo.response() +- returns: A matching [Response] object, or `null` if the response has not been received yet. + + +[string]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type "String" +[Object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Object_type "Object" +[number]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#number_type "number" +[Promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Promise_type "Promise" +[Response]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Response_type "Response" diff --git a/utils/doclint/check_public_api/test/check-nullish/result.txt b/utils/doclint/check_public_api/test/check-nullish/result.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/utils/doclint/check_public_api/test/check-returns/api.ts b/utils/doclint/check_public_api/test/check-returns/api.ts index b97049ce7e0b8..502d2a1c9c4b6 100644 --- a/utils/doclint/check_public_api/test/check-returns/api.ts +++ b/utils/doclint/check_public_api/test/check-returns/api.ts @@ -10,9 +10,8 @@ class Foo { e(); } - www() { - if (1 === 1) - return 'df'; + www() : string { + return 'df'; } async asyncFunction() { diff --git a/utils/doclint/check_public_api/test/test.js b/utils/doclint/check_public_api/test/test.js index cdf7663d7e6fb..5fee72c42c291 100644 --- a/utils/doclint/check_public_api/test/test.js +++ b/utils/doclint/check_public_api/test/test.js @@ -51,6 +51,7 @@ describe('checkPublicAPI', function() { it('check-duplicates', testLint); it('check-sorting', testLint); it('check-returns', testLint); + it('check-nullish', testLint); it('js-builder-common', testJSBuilder); it('js-builder-inheritance', testJSBuilder); it('md-builder-common', testMDBuilder);