Bug 1707588 - [puppeteer] Sync vendored puppeteer to v9.1.1 r=webdriver-reviewers,whimboo
authorJulian Descottes <jdescottes@mozilla.com>
Tue, 15 Jun 2021 07:35:20 +0000
changeset 583207 70e57d0764fb4647178da636e023936d8dbf382c
parent 583206 fb471e85400a2ee6927138dfd5f40557b9b67752
child 583208 af3e019e67c86cd390c1bd152dce239984e30fb4
push id38540
push usersmolnar@mozilla.com
push dateTue, 15 Jun 2021 21:45:02 +0000
treeherdermozilla-central@206721f8064a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswebdriver-reviewers, whimboo
bugs1707588
milestone91.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1707588 - [puppeteer] Sync vendored puppeteer to v9.1.1 r=webdriver-reviewers,whimboo PR to upstream the comment update: https://github.com/puppeteer/puppeteer/pull/7324 Differential Revision: https://phabricator.services.mozilla.com/D117539
remote/test/puppeteer-expected.json
remote/test/puppeteer/.prettierignore
remote/test/puppeteer/CHANGELOG.md
remote/test/puppeteer/CONTRIBUTING.md
remote/test/puppeteer/README.md
remote/test/puppeteer/examples/README.md
remote/test/puppeteer/moz.yaml
remote/test/puppeteer/package-lock.json
remote/test/puppeteer/package.json
remote/test/puppeteer/scripts/test-ts-definition-files.ts
remote/test/puppeteer/src/common/AriaQueryHandler.ts
remote/test/puppeteer/src/common/Browser.ts
remote/test/puppeteer/src/common/BrowserConnector.ts
remote/test/puppeteer/src/common/Connection.ts
remote/test/puppeteer/src/common/ConnectionTransport.ts
remote/test/puppeteer/src/common/ConsoleMessage.ts
remote/test/puppeteer/src/common/Coverage.ts
remote/test/puppeteer/src/common/DOMWorld.ts
remote/test/puppeteer/src/common/DeviceDescriptors.ts
remote/test/puppeteer/src/common/Dialog.ts
remote/test/puppeteer/src/common/Errors.ts
remote/test/puppeteer/src/common/EvalTypes.ts
remote/test/puppeteer/src/common/EventEmitter.ts
remote/test/puppeteer/src/common/ExecutionContext.ts
remote/test/puppeteer/src/common/FileChooser.ts
remote/test/puppeteer/src/common/FrameManager.ts
remote/test/puppeteer/src/common/HTTPRequest.ts
remote/test/puppeteer/src/common/Input.ts
remote/test/puppeteer/src/common/JSHandle.ts
remote/test/puppeteer/src/common/LifecycleWatcher.ts
remote/test/puppeteer/src/common/NetworkManager.ts
remote/test/puppeteer/src/common/PDFOptions.ts
remote/test/puppeteer/src/common/Page.ts
remote/test/puppeteer/src/common/Puppeteer.ts
remote/test/puppeteer/src/common/WebWorker.ts
remote/test/puppeteer/src/common/helper.ts
remote/test/puppeteer/src/node/BrowserFetcher.ts
remote/test/puppeteer/src/node/Launcher.ts
remote/test/puppeteer/src/node/install.ts
remote/test/puppeteer/src/revisions.ts
remote/test/puppeteer/test-ts-types/ts-cjs-import-cjs-output/good.ts
remote/test/puppeteer/test/README.md
remote/test/puppeteer/test/accessibility.spec.ts
remote/test/puppeteer/test/ariaqueryhandler.spec.ts
remote/test/puppeteer/test/browsercontext.spec.ts
remote/test/puppeteer/test/click.spec.ts
remote/test/puppeteer/test/coverage.spec.ts
remote/test/puppeteer/test/dialog.spec.ts
remote/test/puppeteer/test/elementhandle.spec.ts
remote/test/puppeteer/test/emulation.spec.ts
remote/test/puppeteer/test/evaluation.spec.ts
remote/test/puppeteer/test/frame.spec.ts
remote/test/puppeteer/test/idle_override.spec.ts
remote/test/puppeteer/test/ignorehttpserrors.spec.ts
remote/test/puppeteer/test/input.spec.ts
remote/test/puppeteer/test/jshandle.spec.ts
remote/test/puppeteer/test/keyboard.spec.ts
remote/test/puppeteer/test/launcher.spec.ts
remote/test/puppeteer/test/mouse.spec.ts
remote/test/puppeteer/test/navigation.spec.ts
remote/test/puppeteer/test/network.spec.ts
remote/test/puppeteer/test/page.spec.ts
remote/test/puppeteer/test/requestinterception.spec.ts
remote/test/puppeteer/test/screenshot.spec.ts
remote/test/puppeteer/test/target.spec.ts
remote/test/puppeteer/test/touchscreen.spec.ts
remote/test/puppeteer/test/waittask.spec.ts
remote/test/puppeteer/utils/doclint/README.md
remote/test/puppeteer/utils/doclint/check_public_api/index.js
remote/test/puppeteer/vendor/mitt/src/index.ts
remote/test/puppeteer/versions.js
--- a/remote/test/puppeteer-expected.json
+++ b/remote/test/puppeteer-expected.json
@@ -151,38 +151,38 @@
   ],
   "Page.click should not hang with touch-enabled viewports (click.spec.ts)": [
     "PASS"
   ],
   "Page.click should scroll and click the button (click.spec.ts)": [
     "PASS"
   ],
   "Page.click should double click the button (click.spec.ts)": [
-    "PASS"
+    "FAIL", "PASS"
   ],
   "Page.click should click a partially obscured button (click.spec.ts)": [
     "PASS"
   ],
   "Page.click should click a rotated button (click.spec.ts)": [
     "PASS"
   ],
   "Page.click should fire contextmenu event on right click (click.spec.ts)": [
     "PASS"
   ],
   "Page.click should click links which cause navigation (click.spec.ts)": [
     "PASS"
   ],
   "Page.click should click the button inside an iframe (click.spec.ts)": [
-    "PASS"
+    "FAIL", "PASS"
   ],
   "Page.click should click the button with fixed position inside an iframe (click.spec.ts)": [
     "SKIP"
   ],
   "Page.click should click the button with deviceScaleFactor set (click.spec.ts)": [
-    "PASS"
+    "FAIL", "PASS"
   ],
   "Cookie specs Page.cookies should return no cookies in pristine browser context (cookies.spec.ts)": [
     "PASS"
   ],
   "Cookie specs Page.cookies should get a cookie (cookies.spec.ts)": [
     "PASS"
   ],
   "Cookie specs Page.cookies should properly report httpOnly cookie (cookies.spec.ts)": [
@@ -909,16 +909,19 @@
     "PASS"
   ],
   "Launcher specs Puppeteer Puppeteer.connect should be able to close remote browser (launcher.spec.ts)": [
     "PASS"
   ],
   "Launcher specs Puppeteer Puppeteer.connect should support ignoreHTTPSErrors option (launcher.spec.ts)": [
     "PASS"
   ],
+  "Launcher specs Puppeteer Puppeteer.connect should support targetFilter option (launcher.spec.ts)": [
+    "PASS"
+  ],
   "Launcher specs Puppeteer Puppeteer.connect should be able to reconnect to a disconnected browser (launcher.spec.ts)": [
     "PASS"
   ],
   "Launcher specs Puppeteer Puppeteer.connect should be able to connect to the same page simultaneously (launcher.spec.ts)": [
     "FAIL"
   ],
   "Launcher specs Puppeteer Puppeteer.connect should be able to reconnect (launcher.spec.ts)": [
     "FAIL"
@@ -1170,16 +1173,19 @@
     "TIMEOUT"
   ],
   "network Response.statusText should work (network.spec.ts)": [
     "PASS"
   ],
   "network Network Events Page.Events.Request (network.spec.ts)": [
     "FAIL", "PASS"
   ],
+  "network Network Events Page.Events.RequestServedFromCache (network.spec.ts)": [
+    "FAIL"
+  ],
   "network Network Events Page.Events.Response (network.spec.ts)": [
     "PASS", "FAIL"
   ],
   "network Network Events Page.Events.RequestFailed (network.spec.ts)": [
     "FAIL"
   ],
   "network Network Events Page.Events.RequestFinished (network.spec.ts)": [
     "FAIL"
@@ -1209,16 +1215,19 @@
     "TIMEOUT"
   ],
   "network Page.authenticate should fail if wrong credentials (network.spec.ts)": [
     "FAIL"
   ],
   "network Page.authenticate should allow disable authentication (network.spec.ts)": [
     "FAIL"
   ],
+  "network Page.authenticate should not disable caching (network.spec.ts)": [
+    "FAIL"
+  ],
   "Page Page.close should reject all promises when page is closed (page.spec.ts)": [
     "PASS"
   ],
   "Page Page.close should not be visible in browser.pages (page.spec.ts)": [
     "PASS"
   ],
   "Page Page.close should run beforeunload if asked for (page.spec.ts)": [
     "TIMEOUT"
@@ -1767,16 +1776,22 @@
     "FAIL"
   ],
   "request interception Page.setRequestInterception should throw if interception is not enabled (requestinterception.spec.ts)": [
     "PASS"
   ],
   "request interception Page.setRequestInterception should work with file URLs (requestinterception.spec.ts)": [
     "FAIL"
   ],
+  "request interception Page.setRequestInterception should not cache if not cache-safe (requestinterception.spec.ts)": [
+    "FAIL"
+  ],
+  "request interception Page.setRequestInterception should cache if cache-safe (requestinterception.spec.ts)": [
+    "FAIL"
+  ],
   "request interception Request.continue should work (requestinterception.spec.ts)": [
     "FAIL"
   ],
   "request interception Request.continue should amend HTTP headers (requestinterception.spec.ts)": [
     "FAIL"
   ],
   "request interception Request.continue should redirect in a way non-observable to page (requestinterception.spec.ts)": [
     "FAIL"
new file mode 100644
--- /dev/null
+++ b/remote/test/puppeteer/.prettierignore
@@ -0,0 +1,8 @@
+node_modules/
+lib/
+third_party/
+vendor/
+
+package-lock.json
+yarn.lock
+package.json
--- a/remote/test/puppeteer/CHANGELOG.md
+++ b/remote/test/puppeteer/CHANGELOG.md
@@ -1,12 +1,60 @@
 # Changelog
 
 All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
 
+### [9.1.1](https://github.com/puppeteer/puppeteer/compare/v9.1.0...v9.1.1) (2021-05-05)
+
+
+### Bug Fixes
+
+* make targetFilter synchronous ([#7203](https://github.com/puppeteer/puppeteer/issues/7203)) ([bcc85a0](https://github.com/puppeteer/puppeteer/commit/bcc85a0969077d122e5d8d2fb5c1061999a8ae48))
+
+## [9.1.0](https://github.com/puppeteer/puppeteer/compare/v9.0.0...v9.1.0) (2021-05-03)
+
+
+### Features
+
+* add option to filter targets ([#7192](https://github.com/puppeteer/puppeteer/issues/7192)) ([ec3fc2e](https://github.com/puppeteer/puppeteer/commit/ec3fc2e035bb5ca14a576180fff612e1ecf6bad7))
+
+
+### Bug Fixes
+
+* change rm -rf to rimraf ([#7168](https://github.com/puppeteer/puppeteer/issues/7168)) ([ad6b736](https://github.com/puppeteer/puppeteer/commit/ad6b736039436fcc5c0a262e5b575aa041427be3))
+
+## [9.0.0](https://github.com/puppeteer/puppeteer/compare/v8.0.0...v9.0.0) (2021-04-21)
+
+
+### ⚠ BREAKING CHANGES
+
+* **filechooser:** FileChooser.cancel() is now synchronous.
+
+### Features
+
+* **chromium:** roll to Chromium 91.0.4469.0 (r869685) ([#7110](https://github.com/puppeteer/puppeteer/issues/7110)) ([715e7a8](https://github.com/puppeteer/puppeteer/commit/715e7a8d62901d1c7ec602425c2fce8d8148b742))
+* **launcher:** fix installation error on Apple M1 chips ([#7099](https://github.com/puppeteer/puppeteer/issues/7099)) ([c239d9e](https://github.com/puppeteer/puppeteer/commit/c239d9edc72d85697b4875c98fff3ec592848082)), closes [#6622](https://github.com/puppeteer/puppeteer/issues/6622)
+* **network:** request interception and caching compatibility ([#6996](https://github.com/puppeteer/puppeteer/issues/6996)) ([8695759](https://github.com/puppeteer/puppeteer/commit/8695759a223bc1bd31baecb00dc28721216e4c6f))
+* **page:** emit the event after removing the Worker ([#7080](https://github.com/puppeteer/puppeteer/issues/7080)) ([e34a6d5](https://github.com/puppeteer/puppeteer/commit/e34a6d53183c3e1f63a375ba6a26bee0dcfcf542))
+* **types:** improve type of predicate function ([#6997](https://github.com/puppeteer/puppeteer/issues/6997)) ([943477c](https://github.com/puppeteer/puppeteer/commit/943477cc1eb4b129870142873b3554737d5ef252)), closes [/github.com/DefinitelyTyped/DefinitelyTyped/blob/c43191a8f7a7d2a47bbff0bc3a7d95ecc64d2269/types/puppeteer/index.d.ts#L1883-L1885](https://github.com/puppeteer//github.com/DefinitelyTyped/DefinitelyTyped/blob/c43191a8f7a7d2a47bbff0bc3a7d95ecc64d2269/types/puppeteer/index.d.ts/issues/L1883-L1885)
+* accept captureBeyondViewport as optional screenshot param ([#7063](https://github.com/puppeteer/puppeteer/issues/7063)) ([0e092d2](https://github.com/puppeteer/puppeteer/commit/0e092d2ea0ec18ad7f07ad3507deb80f96086e7a))
+* **page:** add omitBackground option for page.pdf method ([#6981](https://github.com/puppeteer/puppeteer/issues/6981)) ([dc8ab6d](https://github.com/puppeteer/puppeteer/commit/dc8ab6d8ca1661f8e56d329e6d9c49c891e8b975))
+
+
+### Bug Fixes
+
+* **aria:** fix parsing of ARIA selectors ([#7037](https://github.com/puppeteer/puppeteer/issues/7037)) ([4426135](https://github.com/puppeteer/puppeteer/commit/4426135692ae3ee7ed2841569dd9375e7ca8286c))
+* **page:** fix mouse.click method ([#7097](https://github.com/puppeteer/puppeteer/issues/7097)) ([ba7c367](https://github.com/puppeteer/puppeteer/commit/ba7c367de33ace7753fd9d8b8cc894b2c14ab6c2)), closes [#6462](https://github.com/puppeteer/puppeteer/issues/6462) [#3347](https://github.com/puppeteer/puppeteer/issues/3347)
+* make `$` and `$$` selectors generic ([#6883](https://github.com/puppeteer/puppeteer/issues/6883)) ([b349c91](https://github.com/puppeteer/puppeteer/commit/b349c91e7df76630b7411d6645e649945c4609bd))
+* type page event listeners correctly ([#6891](https://github.com/puppeteer/puppeteer/issues/6891)) ([866d34e](https://github.com/puppeteer/puppeteer/commit/866d34ee1122e89eab00743246676845bb065968))
+* **typescript:** allow defaultViewport to be 'null' ([#6942](https://github.com/puppeteer/puppeteer/issues/6942)) ([e31e68d](https://github.com/puppeteer/puppeteer/commit/e31e68dfa12dd50482b700472bc98876b9031829)), closes [#6885](https://github.com/puppeteer/puppeteer/issues/6885)
+* make screenshots work in puppeteer-web ([#6936](https://github.com/puppeteer/puppeteer/issues/6936)) ([5f24f60](https://github.com/puppeteer/puppeteer/commit/5f24f608194fd4252da7b288461427cabc9dabb3))
+* **filechooser:** cancel is sync ([#6937](https://github.com/puppeteer/puppeteer/issues/6937)) ([2ba61e0](https://github.com/puppeteer/puppeteer/commit/2ba61e04e923edaac09c92315212552f2d4ce676))
+* **network:** don't disable cache for auth challenge ([#6962](https://github.com/puppeteer/puppeteer/issues/6962)) ([1c2479a](https://github.com/puppeteer/puppeteer/commit/1c2479a6cd4bd09a577175ffd31c40ca6f4279b8))
+
 ## [8.0.0](https://github.com/puppeteer/puppeteer/compare/v7.1.0...v8.0.0) (2021-02-26)
 
 
 ### ⚠ BREAKING CHANGES
 
 * renamed type `ChromeArgOptions` to `BrowserLaunchArgumentOptions`
 * renamed type `BrowserOptions` to `BrowserConnectOptions`
 
--- a/remote/test/puppeteer/CONTRIBUTING.md
+++ b/remote/test/puppeteer/CONTRIBUTING.md
@@ -1,8 +1,9 @@
+<!-- prettier-ignore-start -->
 <!-- gen:toc -->
 - [How to Contribute](#how-to-contribute)
   * [Contributor License Agreement](#contributor-license-agreement)
   * [Getting Code](#getting-code)
   * [Code reviews](#code-reviews)
   * [Code Style](#code-style)
   * [TypeScript guidelines](#typescript-guidelines)
   * [Project structure and TypeScript compilation](#project-structure-and-typescript-compilation)
@@ -16,17 +17,17 @@
   * [Running & Writing Tests](#running--writing-tests)
   * [Public API Coverage](#public-api-coverage)
   * [Debugging Puppeteer](#debugging-puppeteer)
 - [For Project Maintainers](#for-project-maintainers)
   * [Rolling new Chromium version](#rolling-new-chromium-version)
     - [Bisecting upstream changes](#bisecting-upstream-changes)
   * [Releasing to npm](#releasing-to-npm)
 <!-- gen:stop -->
-
+<!-- prettier-ignore-end -->
 # How to Contribute
 
 First of all, thank you for your interest in Puppeteer!
 We'd love to accept your patches and contributions!
 
 ## Contributor License Agreement
 
 Contributions to this project must be accompanied by a Contributor License
@@ -159,16 +160,22 @@ To deliver to a different location, use 
 All public API should have a descriptive entry in [`docs/api.md`](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md). There's a [documentation linter](https://github.com/puppeteer/puppeteer/tree/main/utils/doclint) which makes sure documentation is aligned with the codebase.
 
 To run the documentation linter, use:
 
 ```bash
 npm run doc
 ```
 
+To format the documentation markdown and its code snippets, use:
+
+```bash
+npm run markdownlint-fix
+```
+
 ## Adding New Dependencies
 
 For all dependencies (both installation and development):
 - **Do not add** a dependency if the desired functionality is easily implementable.
 - If adding a dependency, it should be well-maintained and trustworthy.
 
 A barrier for introducing new installation dependencies is especially high:
 - **Do not add** installation dependency unless it's critical to project success.
@@ -250,23 +257,25 @@ See [Debugging Tips](README.md#debugging
 # For Project Maintainers
 
 ## Rolling new Chromium version
 
 The following steps are needed to update the Chromium version.
 
 1. Find a suitable Chromium revision
    Not all revisions have builds for all platforms, so we need to find one that does.
-   To do so, run `utils/check_availability.js -rb` to find the latest suitable beta Chromium revision (see `utils/check_availability.js -help` for more options).
+   To do so, run `utils/check_availability.js -rd` to find the latest suitable `dev` Chromium revision (see `utils/check_availability.js -help` for more options).
 1. Update `src/revisions.ts` with the found revision number.
+1. Update `versions.js` with the new Chromium-to-Puppeteer version mapping.
 1. Run `npm run ensure-correct-devtools-protocol-revision`.
    If it fails, update `package.json` with the expected `devtools-protocol` version.
-1. Run `npm run tsc` and `npm install` and ensure that all tests pass. If a test fails, [bisect](#bisecting-upstream-changes) the upstream cause of the failure, and either update the test expectations accordingly (if it was an intended change) or work around the changes in Puppeteer (if it’s not desirable to change Puppeteer’s observable behavior).
-1. Update `versions.js` with the new Chromium-to-Puppeteer version mapping.
+1. Run `npm run tsc` and `npm install`.
+1. Run `npm run unit` and ensure that all tests pass. If a test fails, [bisect](#bisecting-upstream-changes) the upstream cause of the failure, and either update the test expectations accordingly (if it was an intended change) or work around the changes in Puppeteer (if it’s not desirable to change Puppeteer’s observable behavior).
 1. Commit and push your changes and open a pull request.
+   The commit message must contain the version in `Chromium <version> (<revision>)` format to ensure that [pptr.dev](https://pptr.dev/) can parse it correctly, e.g. `'feat(chromium): roll to Chromium 90.0.4427.0 (r856583)'`.
 
 ### Bisecting upstream changes
 
 Sometimes, performing a Chromium roll causes tests to fail. To figure out the cause, you need to bisect Chromium revisions to figure out the earliest possible revision that changed the behavior. The script in `utils/bisect.js` can be helpful here. Given a Node.js script that calls `process.exit(1)` for bad revisions, run this from the Puppeteer repository’s root directory:
 
 ```sh
 node utils/bisect.js --good 686378 --bad 706915 script.js
 ```
--- a/remote/test/puppeteer/README.md
+++ b/remote/test/puppeteer/README.md
@@ -3,17 +3,17 @@
 <!-- [START badges] -->
 
 [![Build status](https://github.com/puppeteer/puppeteer/workflows/run-checks/badge.svg)](https://github.com/puppeteer/puppeteer/actions?query=workflow%3Arun-checks) [![npm puppeteer package](https://img.shields.io/npm/v/puppeteer.svg)](https://npmjs.org/package/puppeteer)
 
 <!-- [END badges] -->
 
 <img src="https://user-images.githubusercontent.com/10379601/29446482-04f7036a-841f-11e7-9872-91d1fc2ea683.png" height="200" align="right">
 
-###### [API](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md)
+###### [API](https://github.com/puppeteer/puppeteer/blob/v9.1.1/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md)
 
 > Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the [DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). Puppeteer runs [headless](https://developers.google.com/web/updates/2017/04/headless-chrome) by default, but can be configured to run full (non-headless) Chrome or Chromium.
 
 <!-- [START usecases] -->
 
 ###### What can I do?
 
 Most things that you can do manually in the browser can be done using Puppeteer! Here are a few examples to get you started:
@@ -36,17 +36,17 @@ Give it a spin: https://try-puppeteer.ap
 
 To use Puppeteer in your project, run:
 
 ```bash
 npm i puppeteer
 # or "yarn add puppeteer"
 ```
 
-Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, or to download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#environment-variables).
+Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, or to download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v9.1.1/docs/api.md#environment-variables).
 
 ### puppeteer-core
 
 Since version 1.7.0 we publish the [`puppeteer-core`](https://www.npmjs.com/package/puppeteer-core) package,
 a version of Puppeteer that doesn't download any browser by default.
 
 ```bash
 npm i puppeteer-core
@@ -61,17 +61,17 @@ See [puppeteer vs puppeteer-core](https:
 ### Usage
 
 Puppeteer follows the latest [maintenance LTS](https://github.com/nodejs/Release#release-schedule) version of Node.
 
 Note: Prior to v1.18.1, Puppeteer required at least Node v6.4.0. Versions from v1.18.1 to v2.1.0 rely on
 Node 8.9.0+. Starting from v3.0.0 Puppeteer starts to rely on Node 10.18.1+. All examples below use async/await which is only supported in Node v7.6.0 or greater.
 
 Puppeteer will be familiar to people using other browser testing frameworks. You create an instance
-of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#).
+of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v9.1.1/docs/api.md#).
 
 **Example** - navigating to https://example.com and saving a screenshot as _example.png_:
 
 Save file as **example.js**
 
 ```js
 const puppeteer = require('puppeteer');
 
@@ -86,17 +86,17 @@ const puppeteer = require('puppeteer');
 ```
 
 Execute script on the command line
 
 ```bash
 node example.js
 ```
 
-Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#pagesetviewportviewport).
+Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/puppeteer/puppeteer/blob/v9.1.1/docs/api.md#pagesetviewportviewport).
 
 **Example** - create a PDF.
 
 Save file as **hn.js**
 
 ```js
 const puppeteer = require('puppeteer');
 
@@ -113,17 +113,17 @@ const puppeteer = require('puppeteer');
 ```
 
 Execute script on the command line
 
 ```bash
 node hn.js
 ```
 
-See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#pagepdfoptions) for more information about creating pdfs.
+See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v9.1.1/docs/api.md#pagepdfoptions) for more information about creating pdfs.
 
 **Example** - evaluate script in the context of the page
 
 Save file as **get-dimensions.js**
 
 ```js
 const puppeteer = require('puppeteer');
 
@@ -148,55 +148,55 @@ const puppeteer = require('puppeteer');
 ```
 
 Execute script on the command line
 
 ```bash
 node get-dimensions.js
 ```
 
-See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`.
+See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v9.1.1/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`.
 
 <!-- [END getstarted] -->
 
 <!-- [START runtimesettings] -->
 
 ## Default runtime settings
 
 **1. Uses Headless mode**
 
-Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the [`headless` option](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#puppeteerlaunchoptions) when launching a browser:
+Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the [`headless` option](https://github.com/puppeteer/puppeteer/blob/v9.1.1/docs/api.md#puppeteerlaunchoptions) when launching a browser:
 
 ```js
 const browser = await puppeteer.launch({ headless: false }); // default is true
 ```
 
 **2. Runs a bundled version of Chromium**
 
 By default, Puppeteer downloads and uses a specific version of Chromium so its API
 is guaranteed to work out of the box. To use Puppeteer with a different version of Chrome or Chromium,
 pass in the executable's path when creating a `Browser` instance:
 
 ```js
 const browser = await puppeteer.launch({ executablePath: '/path/to/Chrome' });
 ```
 
-You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#puppeteerlaunchoptions) for more information.
+You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v9.1.1/docs/api.md#puppeteerlaunchoptions) for more information.
 
 See [`this article`](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description of the differences between Chromium and Chrome. [`This article`](https://chromium.googlesource.com/chromium/src/+/master/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users.
 
 **3. Creates a fresh user profile**
 
 Puppeteer creates its own browser user profile which it **cleans up on every run**.
 
 <!-- [END runtimesettings] -->
 
 ## Resources
 
-- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md)
+- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v9.1.1/docs/api.md)
 - [Examples](https://github.com/puppeteer/puppeteer/tree/main/examples/)
 - [Community list of Puppeteer resources](https://github.com/transitive-bullshit/awesome-puppeteer)
 
 <!-- [START debugging] -->
 
 ## Debugging tips
 
 1.  Turn off headless mode - sometimes it's useful to see what the browser is
@@ -328,17 +328,17 @@ Check out [contributing guide](https://g
 
 The Chrome DevTools team maintains the library, but we'd love your help and expertise on the project!
 See [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md).
 
 #### Q: What is the status of cross-browser support?
 
 Official Firefox support is currently experimental. The ongoing collaboration with Mozilla aims to support common end-to-end testing use cases, for which developers expect cross-browser coverage. The Puppeteer team needs input from users to stabilize Firefox support and to bring missing APIs to our attention.
 
-From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox.
+From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v9.1.1/docs/api.md#puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox.
 
 We will continue to collaborate with other browser vendors to bring Puppeteer support to browsers such as Safari.
 This effort includes exploration of a standard for executing cross-browser commands (instead of relying on the non-standard DevTools Protocol used by Chrome).
 
 #### Q: What are Puppeteer’s goals and principles?
 
 The goals of the project are:
 
@@ -428,17 +428,17 @@ await page.evaluate(() => {
   document.querySelector('button[type=submit]').click();
 });
 ```
 
 #### Q: What features does Puppeteer not support?
 
 You may find that Puppeteer does not behave as expected when controlling pages that incorporate audio and video. (For example, [video playback/screenshots is likely to fail](https://github.com/puppeteer/puppeteer/issues/291).) There are two reasons for this:
 
-- Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/v8.0.0/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.)
+- Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/v9.1.1/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.)
 - Since Puppeteer (in all configurations) controls a desktop version of Chromium/Chrome, features that are only supported by the mobile version of Chrome are not supported. This means that Puppeteer [does not support HTTP Live Streaming (HLS)](https://caniuse.com/#feat=http-live-streaming).
 
 #### Q: I am having trouble installing / running Puppeteer in my test environment. Where should I look for help?
 
 We have a [troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md) guide for various operating systems that lists the required dependencies.
 
 #### Q: How do I try/test a prerelease version of Puppeteer?
 
@@ -451,13 +451,12 @@ npm i --save puppeteer@next
 Please note that prerelease may be unstable and contain bugs.
 
 #### Q: I have more questions! Where do I ask?
 
 There are many ways to get help on Puppeteer:
 
 - [bugtracker](https://github.com/puppeteer/puppeteer/issues)
 - [Stack Overflow](https://stackoverflow.com/questions/tagged/puppeteer)
-- [slack channel](https://join.slack.com/t/puppeteer/shared_invite/enQtMzU4MjIyMDA5NTM4LWI0YTE0MjM0NWQzYmE2MTRmNjM1ZTBkN2MxNmJmNTIwNTJjMmFhOWFjMGExMDViYjk2YjU2ZmYzMmE1NmExYzc)
 
 Make sure to search these channels before posting your question.
 
 <!-- [END faq] -->
--- a/remote/test/puppeteer/examples/README.md
+++ b/remote/test/puppeteer/examples/README.md
@@ -12,17 +12,17 @@ More complex and use case driven example
 
 # Other resources
 
 > Other useful tools, articles, and projects that use Puppeteer.
 
 ## Rendering and web scraping
 
 - [Puppetron](https://github.com/cheeaun/puppetron) - Demo site that shows how to use Puppeteer and Headless Chrome to render pages. Inspired by [GoogleChrome/rendertron](https://github.com/GoogleChrome/rendertron).
-- [Thal](https://medium.com/@e_mad_ehsan/getting-started-with-puppeteer-and-chrome-headless-for-web-scrapping-6bf5979dee3e "An article on medium") - Getting started with Puppeteer and Chrome Headless for Web Scraping.
+- [Thal](https://medium.com/@e_mad_ehsan/getting-started-with-puppeteer-and-chrome-headless-for-web-scrapping-6bf5979dee3e 'An article on medium') - Getting started with Puppeteer and Chrome Headless for Web Scraping.
 - [pupperender](https://github.com/LasaleFamine/pupperender) - Express middleware that checks the User-Agent header of incoming requests, and if it matches one of a configurable set of bots, render the page using Puppeteer. Useful for PWA rendering.
 - [headless-chrome-crawler](https://github.com/yujiosaka/headless-chrome-crawler) - Crawler that provides simple APIs to manipulate Headless Chrome and allows you to crawl dynamic websites.
 - [puppeteer-examples](https://github.com/checkly/puppeteer-examples) - Puppeteer Headless Chrome examples for real life use cases such as getting useful info from the web pages or common login scenarios.
 - [browserless](https://github.com/joelgriffith/browserless) - Headless Chrome as a service letting you execute Puppeteer scripts remotely. Provides a docker image with configuration for concurrency, launch arguments and more.
 - [Puppeteer Sandbox](https://puppeteersandbox.com) - Puppeteer sandbox environment as a service. Runs Puppeteer scripts and allows saving and embedding them in external sites and markdown files.
 
 ## Testing
 
@@ -30,9 +30,10 @@ More complex and use case driven example
 - [mocha-headless-chrome](https://github.com/direct-adv-interfaces/mocha-headless-chrome) - Tool which runs client-side **mocha** tests in the command line through headless Chrome.
 - [puppeteer-to-istanbul-example](https://github.com/bcoe/puppeteer-to-istanbul-example) - Demo repository demonstrating how to output Puppeteer coverage in Istanbul format.
 - [jest-puppeteer](https://github.com/smooth-code/jest-puppeteer) - (almost) Zero configuration tool for setting up and running Jest and Puppeteer easily. Also includes an assertion library for Puppeteer.
 - [puppeteer-har](https://github.com/Everettss/puppeteer-har) - Generate HAR file with puppeteer.
 - [puppetry](https://puppetry.app/) - A desktop app to build Puppeteer/Jest driven tests without coding.
 - [cucumber-puppeteer-example](https://github.com/mlampedx/cucumber-puppeteer-example) - Example repository demonstrating how to use Puppeeteer and Cucumber for integration testing.
 
 ## Services
+
 - [Checkly](https://checklyhq.com) - Monitoring SaaS that uses Puppeteer to check availability and correctness of web pages and apps.
--- a/remote/test/puppeteer/moz.yaml
+++ b/remote/test/puppeteer/moz.yaml
@@ -1,10 +1,10 @@
 bugzilla:
   component: Agent
   product: Remote Protocol
 origin:
   description: Headless Chrome Node API
   license: Apache-2.0
   name: puppeteer
-  release: v8.0.0
+  release: 59178c10d15e62ce135f7c39b984abe8cd909808
   url: /Users/jdescottes/Development/git/puppeteer
 schema: 1
--- a/remote/test/puppeteer/package-lock.json
+++ b/remote/test/puppeteer/package-lock.json
@@ -1,49 +1,48 @@
 {
   "name": "puppeteer",
-  "version": "8.0.0",
+  "version": "9.1.1",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
     "@babel/code-frame": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
-      "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
-      "dev": true,
-      "requires": {
-        "@babel/highlight": "^7.12.13"
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz",
+      "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==",
+      "dev": true,
+      "requires": {
+        "@babel/highlight": "^7.14.5"
       }
     },
     "@babel/compat-data": {
-      "version": "7.13.8",
-      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.8.tgz",
-      "integrity": "sha512-EaI33z19T4qN3xLXsGf48M2cDqa6ei9tPZlfLdb2HC+e/cFtREiRd8hdSqDbwdLB0/+gLwqJmCYASH0z2bUdog==",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.5.tgz",
+      "integrity": "sha512-kixrYn4JwfAVPa0f2yfzc2AWti6WRRyO3XjWW5PJAvtE11qhSayrrcrEnee05KAtNaPC+EwehE8Qt1UedEVB8w==",
       "dev": true
     },
     "@babel/core": {
-      "version": "7.13.10",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.13.10.tgz",
-      "integrity": "sha512-bfIYcT0BdKeAZrovpMqX2Mx5NrgAckGbwT982AkdS5GNfn3KMGiprlBAtmBcFZRUmpaufS6WZFP8trvx8ptFDw==",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "^7.12.13",
-        "@babel/generator": "^7.13.9",
-        "@babel/helper-compilation-targets": "^7.13.10",
-        "@babel/helper-module-transforms": "^7.13.0",
-        "@babel/helpers": "^7.13.10",
-        "@babel/parser": "^7.13.10",
-        "@babel/template": "^7.12.13",
-        "@babel/traverse": "^7.13.0",
-        "@babel/types": "^7.13.0",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.5.tgz",
+      "integrity": "sha512-RN/AwP2DJmQTZSfiDaD+JQQ/J99KsIpOCfBE5pL+5jJSt7nI3nYGoAXZu+ffYSQ029NLs2DstZb+eR81uuARgg==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.14.5",
+        "@babel/generator": "^7.14.5",
+        "@babel/helper-compilation-targets": "^7.14.5",
+        "@babel/helper-module-transforms": "^7.14.5",
+        "@babel/helpers": "^7.14.5",
+        "@babel/parser": "^7.14.5",
+        "@babel/template": "^7.14.5",
+        "@babel/traverse": "^7.14.5",
+        "@babel/types": "^7.14.5",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.2",
         "json5": "^2.1.2",
-        "lodash": "^4.17.19",
         "semver": "^6.3.0",
         "source-map": "^0.5.0"
       },
       "dependencies": {
         "json5": {
           "version": "2.2.0",
           "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
           "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
@@ -62,213 +61,205 @@
           "version": "0.5.7",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
           "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
           "dev": true
         }
       }
     },
     "@babel/eslint-parser": {
-      "version": "7.13.10",
-      "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.13.10.tgz",
-      "integrity": "sha512-/I1HQ3jGPhIpeBFeI3wO9WwWOnBYpuR0pX0KlkdGcRQAVX9prB/FCS2HBpL7BiFbzhny1YCiBH8MTZD2jJa7Hg==",
-      "dev": true,
-      "requires": {
-        "eslint-scope": "5.1.0",
-        "eslint-visitor-keys": "^1.3.0",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.14.5.tgz",
+      "integrity": "sha512-20BlOHuGf3UXS7z1QPyllM9Gz8SEgcp/UcKeUmdHIFZO6HF1n+3KaLpeyfwWvjY/Os/ynPX3k8qXE/nZ5dw/0g==",
+      "dev": true,
+      "requires": {
+        "eslint-scope": "^5.1.1",
+        "eslint-visitor-keys": "^2.1.0",
         "semver": "^6.3.0"
       },
       "dependencies": {
-        "eslint-scope": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz",
-          "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==",
-          "dev": true,
-          "requires": {
-            "esrecurse": "^4.1.0",
-            "estraverse": "^4.1.1"
-          }
-        },
-        "eslint-visitor-keys": {
-          "version": "1.3.0",
-          "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
-          "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
-          "dev": true
-        },
         "semver": {
           "version": "6.3.0",
           "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
           "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
           "dev": true
         }
       }
     },
     "@babel/generator": {
-      "version": "7.13.9",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz",
-      "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "^7.13.0",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.5.tgz",
+      "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.14.5",
         "jsesc": "^2.5.1",
         "source-map": "^0.5.0"
       },
       "dependencies": {
         "source-map": {
           "version": "0.5.7",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
           "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
           "dev": true
         }
       }
     },
     "@babel/helper-compilation-targets": {
-      "version": "7.13.10",
-      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.10.tgz",
-      "integrity": "sha512-/Xju7Qg1GQO4mHZ/Kcs6Au7gfafgZnwm+a7sy/ow/tV1sHeraRUHbjdat8/UvDor4Tez+siGKDk6zIKtCPKVJA==",
-      "dev": true,
-      "requires": {
-        "@babel/compat-data": "^7.13.8",
-        "@babel/helper-validator-option": "^7.12.17",
-        "browserslist": "^4.14.5",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz",
+      "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==",
+      "dev": true,
+      "requires": {
+        "@babel/compat-data": "^7.14.5",
+        "@babel/helper-validator-option": "^7.14.5",
+        "browserslist": "^4.16.6",
         "semver": "^6.3.0"
       },
       "dependencies": {
         "semver": {
           "version": "6.3.0",
           "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
           "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
           "dev": true
         }
       }
     },
     "@babel/helper-function-name": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz",
-      "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-get-function-arity": "^7.12.13",
-        "@babel/template": "^7.12.13",
-        "@babel/types": "^7.12.13"
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz",
+      "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-get-function-arity": "^7.14.5",
+        "@babel/template": "^7.14.5",
+        "@babel/types": "^7.14.5"
       }
     },
     "@babel/helper-get-function-arity": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz",
-      "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "^7.12.13"
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz",
+      "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.14.5"
+      }
+    },
+    "@babel/helper-hoist-variables": {
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz",
+      "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.14.5"
       }
     },
     "@babel/helper-member-expression-to-functions": {
-      "version": "7.13.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.0.tgz",
-      "integrity": "sha512-yvRf8Ivk62JwisqV1rFRMxiSMDGnN6KH1/mDMmIrij4jztpQNRoHqqMG3U6apYbGRPJpgPalhva9Yd06HlUxJQ==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "^7.13.0"
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.5.tgz",
+      "integrity": "sha512-UxUeEYPrqH1Q/k0yRku1JE7dyfyehNwT6SVkMHvYvPDv4+uu627VXBckVj891BO8ruKBkiDoGnZf4qPDD8abDQ==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.14.5"
       }
     },
     "@babel/helper-module-imports": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz",
-      "integrity": "sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "^7.12.13"
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz",
+      "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.14.5"
       }
     },
     "@babel/helper-module-transforms": {
-      "version": "7.13.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.0.tgz",
-      "integrity": "sha512-Ls8/VBwH577+pw7Ku1QkUWIyRRNHpYlts7+qSqBBFCW3I8QteB9DxfcZ5YJpOwH6Ihe/wn8ch7fMGOP1OhEIvw==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-module-imports": "^7.12.13",
-        "@babel/helper-replace-supers": "^7.13.0",
-        "@babel/helper-simple-access": "^7.12.13",
-        "@babel/helper-split-export-declaration": "^7.12.13",
-        "@babel/helper-validator-identifier": "^7.12.11",
-        "@babel/template": "^7.12.13",
-        "@babel/traverse": "^7.13.0",
-        "@babel/types": "^7.13.0",
-        "lodash": "^4.17.19"
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.5.tgz",
+      "integrity": "sha512-iXpX4KW8LVODuAieD7MzhNjmM6dzYY5tfRqT+R9HDXWl0jPn/djKmA+G9s/2C2T9zggw5tK1QNqZ70USfedOwA==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-module-imports": "^7.14.5",
+        "@babel/helper-replace-supers": "^7.14.5",
+        "@babel/helper-simple-access": "^7.14.5",
+        "@babel/helper-split-export-declaration": "^7.14.5",
+        "@babel/helper-validator-identifier": "^7.14.5",
+        "@babel/template": "^7.14.5",
+        "@babel/traverse": "^7.14.5",
+        "@babel/types": "^7.14.5"
       }
     },
     "@babel/helper-optimise-call-expression": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz",
-      "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "^7.12.13"
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz",
+      "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.14.5"
       }
     },
     "@babel/helper-replace-supers": {
-      "version": "7.13.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.0.tgz",
-      "integrity": "sha512-Segd5me1+Pz+rmN/NFBOplMbZG3SqRJOBlY+mA0SxAv6rjj7zJqr1AVr3SfzUVTLCv7ZLU5FycOM/SBGuLPbZw==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-member-expression-to-functions": "^7.13.0",
-        "@babel/helper-optimise-call-expression": "^7.12.13",
-        "@babel/traverse": "^7.13.0",
-        "@babel/types": "^7.13.0"
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz",
+      "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-member-expression-to-functions": "^7.14.5",
+        "@babel/helper-optimise-call-expression": "^7.14.5",
+        "@babel/traverse": "^7.14.5",
+        "@babel/types": "^7.14.5"
       }
     },
     "@babel/helper-simple-access": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.13.tgz",
-      "integrity": "sha512-0ski5dyYIHEfwpWGx5GPWhH35j342JaflmCeQmsPWcrOQDtCN6C1zKAVRFVbK53lPW2c9TsuLLSUDf0tIGJ5hA==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "^7.12.13"
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz",
+      "integrity": "sha512-nfBN9xvmCt6nrMZjfhkl7i0oTV3yxR4/FztsbOASyTvVcoYd0TRHh7eMLdlEcCqobydC0LAF3LtC92Iwxo0wyw==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.14.5"
       }
     },
     "@babel/helper-split-export-declaration": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz",
-      "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "^7.12.13"
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz",
+      "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.14.5"
       }
     },
     "@babel/helper-validator-identifier": {
-      "version": "7.12.11",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
-      "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
+      "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
       "dev": true
     },
     "@babel/helper-validator-option": {
-      "version": "7.12.17",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz",
-      "integrity": "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz",
+      "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==",
       "dev": true
     },
     "@babel/helpers": {
-      "version": "7.13.10",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.13.10.tgz",
-      "integrity": "sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ==",
-      "dev": true,
-      "requires": {
-        "@babel/template": "^7.12.13",
-        "@babel/traverse": "^7.13.0",
-        "@babel/types": "^7.13.0"
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.5.tgz",
+      "integrity": "sha512-xtcWOuN9VL6nApgVHtq3PPcQv5qFBJzoSZzJ/2c0QK/IP/gxVcoWSNQwFEGvmbQsuS9rhYqjILDGGXcTkA705Q==",
+      "dev": true,
+      "requires": {
+        "@babel/template": "^7.14.5",
+        "@babel/traverse": "^7.14.5",
+        "@babel/types": "^7.14.5"
       }
     },
     "@babel/highlight": {
-      "version": "7.13.10",
-      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz",
-      "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-validator-identifier": "^7.12.11",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
+      "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-validator-identifier": "^7.14.5",
         "chalk": "^2.0.0",
         "js-tokens": "^4.0.0"
       },
       "dependencies": {
         "ansi-styles": {
           "version": "3.2.1",
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
           "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
@@ -316,74 +307,73 @@
           "dev": true,
           "requires": {
             "has-flag": "^3.0.0"
           }
         }
       }
     },
     "@babel/parser": {
-      "version": "7.13.10",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.10.tgz",
-      "integrity": "sha512-0s7Mlrw9uTWkYua7xWr99Wpk2bnGa0ANleKfksYAES8LpWH4gW1OUr42vqKNf0us5UQNfru2wPqMqRITzq/SIQ==",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.5.tgz",
+      "integrity": "sha512-TM8C+xtH/9n1qzX+JNHi7AN2zHMTiPUtspO0ZdHflW8KaskkALhMmuMHb4bCmNdv9VAPzJX3/bXqkVLnAvsPfg==",
       "dev": true
     },
     "@babel/runtime": {
-      "version": "7.13.10",
-      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz",
-      "integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.5.tgz",
+      "integrity": "sha512-121rumjddw9c3NCQ55KGkyE1h/nzWhU/owjhw0l4mQrkzz4x9SGS1X8gFLraHwX7td3Yo4QTL+qj0NcIzN87BA==",
       "dev": true,
       "requires": {
         "regenerator-runtime": "^0.13.4"
       }
     },
     "@babel/template": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz",
-      "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "^7.12.13",
-        "@babel/parser": "^7.12.13",
-        "@babel/types": "^7.12.13"
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz",
+      "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.14.5",
+        "@babel/parser": "^7.14.5",
+        "@babel/types": "^7.14.5"
       }
     },
     "@babel/traverse": {
-      "version": "7.13.0",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.0.tgz",
-      "integrity": "sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ==",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "^7.12.13",
-        "@babel/generator": "^7.13.0",
-        "@babel/helper-function-name": "^7.12.13",
-        "@babel/helper-split-export-declaration": "^7.12.13",
-        "@babel/parser": "^7.13.0",
-        "@babel/types": "^7.13.0",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.5.tgz",
+      "integrity": "sha512-G3BiS15vevepdmFqmUc9X+64y0viZYygubAMO8SvBmKARuF6CPSZtH4Ng9vi/lrWlZFGe3FWdXNy835akH8Glg==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.14.5",
+        "@babel/generator": "^7.14.5",
+        "@babel/helper-function-name": "^7.14.5",
+        "@babel/helper-hoist-variables": "^7.14.5",
+        "@babel/helper-split-export-declaration": "^7.14.5",
+        "@babel/parser": "^7.14.5",
+        "@babel/types": "^7.14.5",
         "debug": "^4.1.0",
-        "globals": "^11.1.0",
-        "lodash": "^4.17.19"
+        "globals": "^11.1.0"
       },
       "dependencies": {
         "globals": {
           "version": "11.12.0",
           "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
           "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
           "dev": true
         }
       }
     },
     "@babel/types": {
-      "version": "7.13.0",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.0.tgz",
-      "integrity": "sha512-hE+HE8rnG1Z6Wzo+MhaKE5lM5eMx71T4EHJgku2E3xIfaULhDcxiiRxUYgwX8qwP1BBSlag+TdGOt6JAidIZTA==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-validator-identifier": "^7.12.11",
-        "lodash": "^4.17.19",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz",
+      "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-validator-identifier": "^7.14.5",
         "to-fast-properties": "^2.0.0"
       }
     },
     "@commitlint/cli": {
       "version": "11.0.0",
       "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-11.0.0.tgz",
       "integrity": "sha512-YWZWg1DuqqO5Zjh7vUOeSX76vm0FFyz4y0cpGMFhrhvUi5unc4IVfCXZ6337R9zxuBtmveiRuuhQqnRRer+13g==",
       "dev": true,
@@ -581,37 +571,52 @@
     },
     "@commitlint/types": {
       "version": "11.0.0",
       "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-11.0.0.tgz",
       "integrity": "sha512-VoNqai1vR5anRF5Tuh/+SWDFk7xi7oMwHrHrbm1BprYXjB2RJsWLhUrStMssDxEl5lW/z3EUdg8RvH/IUBccSQ==",
       "dev": true
     },
     "@eslint/eslintrc": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz",
-      "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==",
+      "version": "0.4.2",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz",
+      "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==",
       "dev": true,
       "requires": {
         "ajv": "^6.12.4",
         "debug": "^4.1.1",
         "espree": "^7.3.0",
-        "globals": "^12.1.0",
+        "globals": "^13.9.0",
         "ignore": "^4.0.6",
         "import-fresh": "^3.2.1",
         "js-yaml": "^3.13.1",
         "minimatch": "^3.0.4",
         "strip-json-comments": "^3.1.1"
       },
       "dependencies": {
+        "globals": {
+          "version": "13.9.0",
+          "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz",
+          "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==",
+          "dev": true,
+          "requires": {
+            "type-fest": "^0.20.2"
+          }
+        },
         "ignore": {
           "version": "4.0.6",
           "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
           "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
           "dev": true
+        },
+        "type-fest": {
+          "version": "0.20.2",
+          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+          "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+          "dev": true
         }
       }
     },
     "@jest/types": {
       "version": "25.5.0",
       "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.5.0.tgz",
       "integrity": "sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==",
       "dev": true,
@@ -718,45 +723,45 @@
     },
     "@microsoft/tsdoc": {
       "version": "0.12.24",
       "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.12.24.tgz",
       "integrity": "sha512-Mfmij13RUTmHEMi9vRUhMXD7rnGR2VvxeNYtaGtaJ4redwwjT4UXYJ+nzmVJF7hhd4pn/Fx5sncDKxMVFJSWPg==",
       "dev": true
     },
     "@nodelib/fs.scandir": {
-      "version": "2.1.4",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
-      "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==",
-      "dev": true,
-      "requires": {
-        "@nodelib/fs.stat": "2.0.4",
+      "version": "2.1.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+      "dev": true,
+      "requires": {
+        "@nodelib/fs.stat": "2.0.5",
         "run-parallel": "^1.1.9"
       }
     },
     "@nodelib/fs.stat": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz",
-      "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==",
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
       "dev": true
     },
     "@nodelib/fs.walk": {
-      "version": "1.2.6",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz",
-      "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==",
-      "dev": true,
-      "requires": {
-        "@nodelib/fs.scandir": "2.1.4",
+      "version": "1.2.7",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz",
+      "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==",
+      "dev": true,
+      "requires": {
+        "@nodelib/fs.scandir": "2.1.5",
         "fastq": "^1.6.0"
       }
     },
     "@rollup/plugin-node-resolve": {
-      "version": "11.2.0",
-      "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.0.tgz",
-      "integrity": "sha512-qHjNIKYt5pCcn+5RUBQxK8krhRvf1HnyVgUCcFFcweDS7fhkOLZeYh0mhHK6Ery8/bb9tvN/ubPzmfF0qjDCTA==",
+      "version": "11.2.1",
+      "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz",
+      "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==",
       "dev": true,
       "requires": {
         "@rollup/pluginutils": "^3.1.0",
         "@types/resolve": "1.17.1",
         "builtin-modules": "^3.1.0",
         "deepmerge": "^4.2.2",
         "is-module": "^1.0.0",
         "resolve": "^1.19.0"
@@ -862,19 +867,19 @@
       "requires": {
         "@types/argparse": "1.0.38",
         "argparse": "~1.0.9",
         "colors": "~1.2.1",
         "string-argv": "~0.3.1"
       }
     },
     "@sinonjs/commons": {
-      "version": "1.8.2",
-      "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz",
-      "integrity": "sha512-sruwd86RJHdsVf/AtBoijDmUqJp3B6hF/DGC23C+JaegnDHaZyewCjoVGTdg3J0uz3Zs7NnIT05OBOmML72lQw==",
+      "version": "1.8.3",
+      "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz",
+      "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==",
       "dev": true,
       "requires": {
         "type-detect": "4.0.8"
       }
     },
     "@sinonjs/fake-timers": {
       "version": "6.0.1",
       "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz",
@@ -989,31 +994,31 @@
     },
     "@types/estree": {
       "version": "0.0.39",
       "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
       "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
       "dev": true
     },
     "@types/express": {
-      "version": "4.17.11",
-      "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.11.tgz",
-      "integrity": "sha512-no+R6rW60JEc59977wIxreQVsIEOAYwgCqldrA/vkpCnbD7MqTefO97lmoBe4WE0F156bC4uLSP1XHDOySnChg==",
+      "version": "4.17.12",
+      "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.12.tgz",
+      "integrity": "sha512-pTYas6FrP15B1Oa0bkN5tQMNqOcVXa9j4FTFtO8DWI9kppKib+6NJtfTOOLcwxuuYvcX2+dVG6et1SxW/Kc17Q==",
       "dev": true,
       "requires": {
         "@types/body-parser": "*",
         "@types/express-serve-static-core": "^4.17.18",
         "@types/qs": "*",
         "@types/serve-static": "*"
       }
     },
     "@types/express-serve-static-core": {
-      "version": "4.17.18",
-      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz",
-      "integrity": "sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA==",
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.21.tgz",
+      "integrity": "sha512-gwCiEZqW6f7EoR8TTEfalyEhb1zA5jQJnRngr97+3pzMaO1RKoI1w2bw07TK72renMUVWcWS5mLI6rk1NqN0nA==",
       "dev": true,
       "requires": {
         "@types/node": "*",
         "@types/qs": "*",
         "@types/range-parser": "*"
       }
     },
     "@types/glob": {
@@ -1049,19 +1054,19 @@
       "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
       "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==",
       "dev": true,
       "requires": {
         "@types/istanbul-lib-coverage": "*"
       }
     },
     "@types/istanbul-reports": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz",
-      "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==",
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz",
+      "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==",
       "dev": true,
       "requires": {
         "@types/istanbul-lib-report": "*"
       }
     },
     "@types/json-schema": {
       "version": "7.0.7",
       "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
@@ -1076,19 +1081,19 @@
     },
     "@types/keygrip": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz",
       "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==",
       "dev": true
     },
     "@types/koa": {
-      "version": "2.13.1",
-      "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.13.1.tgz",
-      "integrity": "sha512-Qbno7FWom9nNqu0yHZ6A0+RWt4mrYBhw3wpBAQ3+IuzGcLlfeYkzZrnMq5wsxulN2np8M4KKeUpTodsOsSad5Q==",
+      "version": "2.13.3",
+      "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.13.3.tgz",
+      "integrity": "sha512-TaujBV+Dhe/FvmSMZJtCFBms+bqQacgUebk/M2C2tq8iGmHE/DDf4DcW2Hc7NqusVZmy5xzrWOjtdPKNP+fTfw==",
       "dev": true,
       "requires": {
         "@types/accepts": "*",
         "@types/content-disposition": "*",
         "@types/cookies": "*",
         "@types/http-assert": "*",
         "@types/http-errors": "*",
         "@types/keygrip": "*",
@@ -1107,19 +1112,19 @@
     },
     "@types/mime": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz",
       "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==",
       "dev": true
     },
     "@types/minimatch": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
-      "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==",
       "dev": true
     },
     "@types/minimist": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.1.tgz",
       "integrity": "sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==",
       "dev": true
     },
@@ -1127,17 +1132,18 @@
       "version": "7.0.2",
       "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz",
       "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==",
       "dev": true
     },
     "@types/node": {
       "version": "14.14.33",
       "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.33.tgz",
-      "integrity": "sha512-oJqcTrgPUF29oUP8AsUqbXGJNuPutsetaa9kTQAQce5Lx5dTYWV02ScBiT/k1BX/Z7pKeqedmvp39Wu4zR7N7g=="
+      "integrity": "sha512-oJqcTrgPUF29oUP8AsUqbXGJNuPutsetaa9kTQAQce5Lx5dTYWV02ScBiT/k1BX/Z7pKeqedmvp39Wu4zR7N7g==",
+      "dev": true
     },
     "@types/normalize-package-data": {
       "version": "2.4.0",
       "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
       "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
       "dev": true
     },
     "@types/parse-json": {
@@ -1282,16 +1288,24 @@
     },
     "@types/yauzl": {
       "version": "2.9.1",
       "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz",
       "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==",
       "optional": true,
       "requires": {
         "@types/node": "*"
+      },
+      "dependencies": {
+        "@types/node": {
+          "version": "15.12.2",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz",
+          "integrity": "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==",
+          "optional": true
+        }
       }
     },
     "@typescript-eslint/eslint-plugin": {
       "version": "4.17.0",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.17.0.tgz",
       "integrity": "sha512-/fKFDcoHg8oNan39IKFOb5WmV7oWhQe1K6CDaAVfJaNWEhmfqlA24g+u1lqU5bMH7zuNasfMId4LaYWC5ijRLw==",
       "dev": true,
       "requires": {
@@ -1374,113 +1388,113 @@
     },
     "@ungap/promise-all-settled": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
       "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==",
       "dev": true
     },
     "@web/browser-logs": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/@web/browser-logs/-/browser-logs-0.2.1.tgz",
-      "integrity": "sha512-nSfRl/+7XQOtXBBJ9FMdXAb1bzytud1LeJAJmBX4bsfMDDcfrr4vNhiX4OnQ5tBYsXoiQse8ZvwngFM2O6PD3A==",
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/@web/browser-logs/-/browser-logs-0.2.3.tgz",
+      "integrity": "sha512-Ylp/5S07j1P/mO2EsCBMGJ8piwh2RWh9h4G/b1gapQvq85XaphjMA2S/dug4DOHJ15OdhMqbgVJPQ5edLXnW4w==",
       "dev": true,
       "requires": {
         "errorstacks": "^2.2.0"
       }
     },
     "@web/config-loader": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/@web/config-loader/-/config-loader-0.1.3.tgz",
       "integrity": "sha512-XVKH79pk4d3EHRhofete8eAnqto1e8mCRAqPV00KLNFzCWSe8sWmLnqKCqkPNARC6nksMaGrATnA5sPDRllMpQ==",
       "dev": true,
       "requires": {
         "semver": "^7.3.4"
       },
       "dependencies": {
         "semver": {
-          "version": "7.3.4",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
-          "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
+          "version": "7.3.5",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+          "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
           "dev": true,
           "requires": {
             "lru-cache": "^6.0.0"
           }
         }
       }
     },
     "@web/dev-server": {
-      "version": "0.1.8",
-      "resolved": "https://registry.npmjs.org/@web/dev-server/-/dev-server-0.1.8.tgz",
-      "integrity": "sha512-HBxzKfRf2XENgTDgCRQ+dQ4F5TQFAMvsr5mB/KYBWKMJJ4PXHRYbfCFvhAgq6s2CrZzicGWp7VZpMHLEVjEqpQ==",
+      "version": "0.1.17",
+      "resolved": "https://registry.npmjs.org/@web/dev-server/-/dev-server-0.1.17.tgz",
+      "integrity": "sha512-2gdOjkQp97uaORkOL8X90f4retqZ2lA9YqHDljpf4SFg0JWoY8X7EJA9XQG1jJ2x46oQ5zqJX7AiSWc47B2k6A==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.12.11",
         "@rollup/plugin-node-resolve": "^11.0.1",
         "@types/command-line-args": "^5.0.0",
         "@web/config-loader": "^0.1.3",
-        "@web/dev-server-core": "^0.3.7",
-        "@web/dev-server-rollup": "^0.3.2",
+        "@web/dev-server-core": "^0.3.12",
+        "@web/dev-server-rollup": "^0.3.3",
         "camelcase": "^6.2.0",
         "chalk": "^4.1.0",
         "command-line-args": "^5.1.1",
         "command-line-usage": "^6.1.1",
         "debounce": "^1.2.0",
         "deepmerge": "^4.2.2",
         "ip": "^1.1.5",
-        "open": "^7.3.0",
+        "open": "^8.0.2",
         "portfinder": "^1.0.28"
       },
       "dependencies": {
         "camelcase": {
           "version": "6.2.0",
           "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz",
           "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==",
           "dev": true
         }
       }
     },
     "@web/dev-server-core": {
-      "version": "0.3.7",
-      "resolved": "https://registry.npmjs.org/@web/dev-server-core/-/dev-server-core-0.3.7.tgz",
-      "integrity": "sha512-uJJMe8V2hLTM6EYrmlzldT7W5TH0L6Sn2DX1YvNT6fx+ztNDhDwH46RJwmDix3+fUqP9Th0iaZ/BJc45T76+Bw==",
+      "version": "0.3.13",
+      "resolved": "https://registry.npmjs.org/@web/dev-server-core/-/dev-server-core-0.3.13.tgz",
+      "integrity": "sha512-bGJHPeFRWATNfuL9Pp2LfqhnmqhBCc5eOO5AWQa0X+WQAwHiFo6xZNfsvsnJ1gvxXgsE4jKBAGu9lQRisvFRFA==",
       "dev": true,
       "requires": {
         "@types/koa": "^2.11.6",
         "@types/ws": "^7.4.0",
         "@web/parse5-utils": "^1.2.0",
         "chokidar": "^3.4.3",
         "clone": "^2.1.2",
-        "es-module-lexer": "^0.3.26",
+        "es-module-lexer": "^0.4.0",
         "get-stream": "^6.0.0",
         "is-stream": "^2.0.0",
         "isbinaryfile": "^4.0.6",
         "koa": "^2.13.0",
         "koa-etag": "^4.0.0",
         "koa-send": "^5.0.1",
         "koa-static": "^5.0.0",
         "lru-cache": "^6.0.0",
         "mime-types": "^2.1.27",
         "parse5": "^6.0.1",
         "picomatch": "^2.2.2",
         "ws": "^7.4.2"
       },
       "dependencies": {
         "get-stream": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz",
-          "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==",
+          "version": "6.0.1",
+          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+          "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
           "dev": true
         }
       }
     },
     "@web/dev-server-rollup": {
-      "version": "0.3.2",
-      "resolved": "https://registry.npmjs.org/@web/dev-server-rollup/-/dev-server-rollup-0.3.2.tgz",
-      "integrity": "sha512-c5ROnMAUrOJPXTQFFXZiOy0ta4Y5yXLA2QkD71htNhIcqeOI4yx6ueDtuFqovRxVI0qcWGk46UdfZ0UGT/9MIg==",
+      "version": "0.3.4",
+      "resolved": "https://registry.npmjs.org/@web/dev-server-rollup/-/dev-server-rollup-0.3.4.tgz",
+      "integrity": "sha512-QFaqHpJXri1TuN1yN0N670bxF5noC1RtIHPhoM5Sp6YX7v3610Z/fq465V7fNaeHnTNN7dIUmNkK9vqLIrsYTg==",
       "dev": true,
       "requires": {
         "@web/dev-server-core": "^0.3.3",
         "chalk": "^4.1.0",
         "parse5": "^6.0.1",
         "rollup": "^2.35.1",
         "whatwg-url": "^8.4.0"
       }
@@ -1542,69 +1556,67 @@
       "requires": {
         "@web/test-runner-core": "^0.10.8",
         "@web/test-runner-coverage-v8": "^0.4.5",
         "chrome-launcher": "^0.13.4",
         "puppeteer-core": "^5.5.0"
       }
     },
     "@web/test-runner-commands": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/@web/test-runner-commands/-/test-runner-commands-0.4.1.tgz",
-      "integrity": "sha512-y1U9+jucQ1ZB9YRgMFIjXTUSu/in54yt4Lf4GcY9fHoSyGVWDub085ARWipmagsD9SRN1QnIYTkMk+jRa/EiLQ==",
-      "dev": true,
-      "requires": {
-        "@web/test-runner-core": "^0.10.8"
+      "version": "0.4.5",
+      "resolved": "https://registry.npmjs.org/@web/test-runner-commands/-/test-runner-commands-0.4.5.tgz",
+      "integrity": "sha512-jbhsS+nZmnbZPj/XL/g4se1c9TRtIgwrlYpaIIcWkHhCu5mKbdipgZ/nlFIhFS9UaVY52NiulmVj6dhAx7w4SA==",
+      "dev": true,
+      "requires": {
+        "@web/test-runner-core": "^0.10.14",
+        "mkdirp": "^1.0.4"
+      },
+      "dependencies": {
+        "mkdirp": {
+          "version": "1.0.4",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+          "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+          "dev": true
+        }
       }
     },
     "@web/test-runner-core": {
-      "version": "0.10.13",
-      "resolved": "https://registry.npmjs.org/@web/test-runner-core/-/test-runner-core-0.10.13.tgz",
-      "integrity": "sha512-w6seztsj/UKUz9HP5KeMZ1JdUadt293SplsrKKaUJTZDMLO8+xvyo+vpt1Mv7zICu0wyuQN0AdD3GjKKX6dFHw==",
+      "version": "0.10.17",
+      "resolved": "https://registry.npmjs.org/@web/test-runner-core/-/test-runner-core-0.10.17.tgz",
+      "integrity": "sha512-T8yLQ6W4tHwREEYlAvAMYXpNkRE4XBynuWQQVq1qf5hf/IFNdYkOVELkgsHevtYLRElxi9/wHeRrn1SkDgj0Ug==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.12.11",
         "@types/co-body": "^5.1.0",
         "@types/convert-source-map": "^1.5.1",
         "@types/debounce": "^1.2.0",
         "@types/istanbul-lib-coverage": "^2.0.3",
         "@types/istanbul-reports": "^3.0.0",
         "@types/uuid": "^8.3.0",
         "@web/browser-logs": "^0.2.1",
-        "@web/dev-server-core": "^0.3.6",
+        "@web/dev-server-core": "^0.3.12",
         "chalk": "^4.1.0",
         "chokidar": "^3.4.3",
         "cli-cursor": "^3.1.0",
         "co-body": "^6.1.0",
         "convert-source-map": "^1.7.0",
         "debounce": "^1.2.0",
-        "dependency-graph": "^0.10.0",
+        "dependency-graph": "^0.11.0",
         "globby": "^11.0.1",
         "ip": "^1.1.5",
         "istanbul-lib-coverage": "^3.0.0",
         "istanbul-lib-report": "^3.0.0",
         "istanbul-reports": "^3.0.2",
         "log-update": "^4.0.0",
         "open": "^8.0.2",
         "picomatch": "^2.2.2",
         "source-map": "^0.7.3",
         "uuid": "^8.3.2"
       },
       "dependencies": {
-        "open": {
-          "version": "8.0.2",
-          "resolved": "https://registry.npmjs.org/open/-/open-8.0.2.tgz",
-          "integrity": "sha512-NV5QmWJrTaNBLHABJyrb+nd5dXI5zfea/suWawBhkHzAbVhLLiJdrqMgxMypGK9Eznp2Ltoh7SAVkQ3XAucX7Q==",
-          "dev": true,
-          "requires": {
-            "define-lazy-prop": "^2.0.0",
-            "is-docker": "^2.1.1",
-            "is-wsl": "^2.2.0"
-          }
-        },
         "source-map": {
           "version": "0.7.3",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
           "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
           "dev": true
         }
       }
     },
@@ -1626,19 +1638,19 @@
       "integrity": "sha512-UsaLvJ0k5Kb53WegF0J0pmKxCLdo6Nxl7GHYykO7m99Irz+jIGXV7VJP9/b8t+HH3fHyqB2Nmd5q9oxXwIJyNw==",
       "dev": true,
       "requires": {
         "@types/mocha": "^8.2.0",
         "@web/test-runner-core": "^0.10.8"
       },
       "dependencies": {
         "@types/mocha": {
-          "version": "8.2.1",
-          "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.1.tgz",
-          "integrity": "sha512-NysN+bNqj6E0Hv4CTGWSlPzMW6vTKjDpOteycDkV4IWBsO+PU48JonrPzV9ODjiI2XrjmA05KInLgF5ivZ/YGQ==",
+          "version": "8.2.2",
+          "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz",
+          "integrity": "sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==",
           "dev": true
         }
       }
     },
     "JSONStream": {
       "version": "1.3.5",
       "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
       "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
@@ -1698,28 +1710,28 @@
     },
     "ansi-colors": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
       "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
       "dev": true
     },
     "ansi-escapes": {
-      "version": "4.3.1",
-      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz",
-      "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==",
-      "dev": true,
-      "requires": {
-        "type-fest": "^0.11.0"
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+      "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+      "dev": true,
+      "requires": {
+        "type-fest": "^0.21.3"
       },
       "dependencies": {
         "type-fest": {
-          "version": "0.11.0",
-          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz",
-          "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==",
+          "version": "0.21.3",
+          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+          "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
           "dev": true
         }
       }
     },
     "ansi-regex": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
       "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
@@ -1736,19 +1748,19 @@
     },
     "any-promise": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
       "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=",
       "dev": true
     },
     "anymatch": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
-      "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+      "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
       "dev": true,
       "requires": {
         "normalize-path": "^3.0.0",
         "picomatch": "^2.0.4"
       }
     },
     "arg": {
       "version": "4.1.3",
@@ -1836,19 +1848,19 @@
     },
     "at-least-node": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
       "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
       "dev": true
     },
     "balanced-match": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
-      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
     },
     "base64-js": {
       "version": "1.5.1",
       "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
       "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
     },
     "binary-extensions": {
       "version": "2.2.0",
@@ -1886,26 +1898,26 @@
     },
     "browser-stdout": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
       "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
       "dev": true
     },
     "browserslist": {
-      "version": "4.16.3",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz",
-      "integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==",
-      "dev": true,
-      "requires": {
-        "caniuse-lite": "^1.0.30001181",
-        "colorette": "^1.2.1",
-        "electron-to-chromium": "^1.3.649",
+      "version": "4.16.6",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz",
+      "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==",
+      "dev": true,
+      "requires": {
+        "caniuse-lite": "^1.0.30001219",
+        "colorette": "^1.2.2",
+        "electron-to-chromium": "^1.3.723",
         "escalade": "^3.1.1",
-        "node-releases": "^1.1.70"
+        "node-releases": "^1.1.71"
       }
     },
     "buffer": {
       "version": "5.7.1",
       "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
       "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
       "requires": {
         "base64-js": "^1.3.1",
@@ -1974,19 +1986,19 @@
       "dev": true,
       "requires": {
         "camelcase": "^5.3.1",
         "map-obj": "^4.0.0",
         "quick-lru": "^4.0.1"
       }
     },
     "caniuse-lite": {
-      "version": "1.0.30001198",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001198.tgz",
-      "integrity": "sha512-r5GGgESqOPZzwvdLVER374FpQu2WluCF1Z2DSiFJ89KSmGjT0LVKjgv4NcAqHmGWF9ihNpqRI9KXO9Ex4sKsgA==",
+      "version": "1.0.30001236",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001236.tgz",
+      "integrity": "sha512-o0PRQSrSCGJKCPZcgMzl5fUaj5xHe8qA2m4QRvnyY4e1lITqoNkr7q/Oh1NcpGSy0Th97UZ35yoKcINPoq7YOQ==",
       "dev": true
     },
     "chalk": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
       "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
       "dev": true,
       "requires": {
@@ -2144,19 +2156,19 @@
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
           "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
           "dev": true,
           "requires": {
             "color-convert": "^1.9.0"
           }
         },
         "array-back": {
-          "version": "4.0.1",
-          "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz",
-          "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==",
+          "version": "4.0.2",
+          "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz",
+          "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==",
           "dev": true
         },
         "chalk": {
           "version": "2.4.2",
           "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
           "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
           "dev": true,
           "requires": {
@@ -2333,19 +2345,19 @@
     },
     "conventional-changelog-config-spec": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz",
       "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==",
       "dev": true
     },
     "conventional-changelog-conventionalcommits": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.5.0.tgz",
-      "integrity": "sha512-buge9xDvjjOxJlyxUnar/+6i/aVEVGA7EEh4OafBCXPlLUQPGbRUBhBUveWRxzvR8TEjhKEP4BdepnpG2FSZXw==",
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.0.tgz",
+      "integrity": "sha512-sj9tj3z5cnHaSJCYObA9nISf7eq/YjscLPoq6nmew4SiOjxqL2KRpK20fjnjVbpNDjJ2HR3MoVcWKXwbVvzS0A==",
       "dev": true,
       "requires": {
         "compare-func": "^2.0.0",
         "lodash": "^4.17.15",
         "q": "^1.5.1"
       }
     },
     "conventional-changelog-core": {
@@ -2376,19 +2388,19 @@
           "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
           "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
           "dev": true,
           "requires": {
             "locate-path": "^2.0.0"
           }
         },
         "hosted-git-info": {
-          "version": "2.8.8",
-          "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
-          "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+          "version": "2.8.9",
+          "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+          "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
           "dev": true
         },
         "load-json-file": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
           "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
           "dev": true,
           "requires": {
@@ -2648,19 +2660,19 @@
       "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==",
       "dev": true,
       "requires": {
         "depd": "~2.0.0",
         "keygrip": "~1.1.0"
       }
     },
     "core-js": {
-      "version": "3.9.1",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.9.1.tgz",
-      "integrity": "sha512-gSjRvzkxQc1zjM/5paAmL4idJBFzuJoo+jDjF1tStYFMV2ERfD02HhahhCGXUyHxQRG4yFKVSdO6g62eoRMcDg==",
+      "version": "3.14.0",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.14.0.tgz",
+      "integrity": "sha512-3s+ed8er9ahK+zJpp9ZtuVcDoFzHNiZsPbNAAE4KXgrRHbjSqqNN6xGSXq6bq7TZIbKj4NLrLb6bJ5i+vSVjHA==",
       "dev": true
     },
     "core-util-is": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
       "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
       "dev": true
     },
@@ -2809,43 +2821,43 @@
     },
     "depd": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
       "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
       "dev": true
     },
     "dependency-graph": {
-      "version": "0.10.0",
-      "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.10.0.tgz",
-      "integrity": "sha512-c9amUgpgxSi1bE5/sbLwcs5diLD0ygCQYmhfM5H1s5VH1mCsYkcmAL3CcNdv4kdSw6JuMoHeDGzLgj/gAXdWVg==",
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz",
+      "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==",
       "dev": true
     },
     "destroy": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
       "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
       "dev": true
     },
     "detect-indent": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz",
-      "integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==",
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
+      "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
       "dev": true
     },
     "detect-newline": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
       "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
       "dev": true
     },
     "devtools-protocol": {
-      "version": "0.0.854822",
-      "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.854822.tgz",
-      "integrity": "sha512-xd4D8kHQtB0KtWW0c9xBZD5LVtm9chkMOfs/3Yn01RhT/sFIsVtzTtypfKoFfWBaL+7xCYLxjOLkhwPXaX/Kcg=="
+      "version": "0.0.869402",
+      "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.869402.tgz",
+      "integrity": "sha512-VvlVYY+VDJe639yHs5PHISzdWTLL3Aw8rO4cvUtwvoxFd6FHbE4OpHHcde52M6096uYYazAmd4l0o5VuFRO2WA=="
     },
     "diff": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
       "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
       "dev": true
     },
     "diff-sequences": {
@@ -2929,19 +2941,19 @@
     },
     "ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
       "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
       "dev": true
     },
     "electron-to-chromium": {
-      "version": "1.3.685",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.685.tgz",
-      "integrity": "sha512-C3oFZNkJ8lz85ADqr3hzpjBc2ciejMRN2SCd/D0hwcqpr6MGxfdN/j89VN6l+ERTuCUvhg0VYsf40Q4qTz4bhQ==",
+      "version": "1.3.752",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.752.tgz",
+      "integrity": "sha512-2Tg+7jSl3oPxgsBsWKh5H83QazTkmWG/cnNwJplmyZc7KcN61+I10oUgaXSVk/NwfvN3BdkKDR4FYuRBQQ2v0A==",
       "dev": true
     },
     "emoji-regex": {
       "version": "8.0.0",
       "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
       "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
       "dev": true
     },
@@ -2979,49 +2991,49 @@
       "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
       "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
       "dev": true,
       "requires": {
         "is-arrayish": "^0.2.1"
       }
     },
     "errorstacks": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/errorstacks/-/errorstacks-2.3.0.tgz",
-      "integrity": "sha512-VjCIUbEyLymy2N1M/uTniewz+j69YC2R7Sp1UiJn04RHwyIniBib6hUZwgmphAAZTOk7LRg/wryGFEJhblEd7Q==",
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/errorstacks/-/errorstacks-2.3.2.tgz",
+      "integrity": "sha512-cJp8qf5t2cXmVZJjZVrcU4ODFJeQOcUyjJEtPFtWO+3N6JPM6vCe4Sfv3cwIs/qS7gnUo/fvKX/mDCVQZq+P7A==",
       "dev": true
     },
     "es-abstract": {
-      "version": "1.18.0",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz",
-      "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==",
+      "version": "1.18.3",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz",
+      "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==",
       "dev": true,
       "requires": {
         "call-bind": "^1.0.2",
         "es-to-primitive": "^1.2.1",
         "function-bind": "^1.1.1",
         "get-intrinsic": "^1.1.1",
         "has": "^1.0.3",
         "has-symbols": "^1.0.2",
         "is-callable": "^1.2.3",
         "is-negative-zero": "^2.0.1",
-        "is-regex": "^1.1.2",
-        "is-string": "^1.0.5",
-        "object-inspect": "^1.9.0",
+        "is-regex": "^1.1.3",
+        "is-string": "^1.0.6",
+        "object-inspect": "^1.10.3",
         "object-keys": "^1.1.1",
         "object.assign": "^4.1.2",
         "string.prototype.trimend": "^1.0.4",
         "string.prototype.trimstart": "^1.0.4",
-        "unbox-primitive": "^1.0.0"
+        "unbox-primitive": "^1.0.1"
       }
     },
     "es-module-lexer": {
-      "version": "0.3.26",
-      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.3.26.tgz",
-      "integrity": "sha512-Va0Q/xqtrss45hWzP8CZJwzGSZJjDM5/MJRE3IXXnUCcVLElR9BRaE9F62BopysASyc4nM3uwhSW7FFB9nlWAA==",
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz",
+      "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==",
       "dev": true
     },
     "es-to-primitive": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
       "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
       "dev": true,
       "requires": {
@@ -3160,32 +3172,32 @@
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
           "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
           "dev": true
         }
       }
     },
     "eslint-module-utils": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz",
-      "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==",
-      "dev": true,
-      "requires": {
-        "debug": "^2.6.9",
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz",
+      "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==",
+      "dev": true,
+      "requires": {
+        "debug": "^3.2.7",
         "pkg-dir": "^2.0.0"
       },
       "dependencies": {
         "debug": {
-          "version": "2.6.9",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "version": "3.2.7",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+          "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
           "dev": true,
           "requires": {
-            "ms": "2.0.0"
+            "ms": "^2.1.1"
           }
         },
         "find-up": {
           "version": "2.1.0",
           "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
           "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
           "dev": true,
           "requires": {
@@ -3197,22 +3209,16 @@
           "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
           "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
           "dev": true,
           "requires": {
             "p-locate": "^2.0.0",
             "path-exists": "^3.0.0"
           }
         },
-        "ms": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-          "dev": true
-        },
         "p-limit": {
           "version": "1.3.0",
           "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
           "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
           "dev": true,
           "requires": {
             "p-try": "^1.0.0"
           }
@@ -3294,19 +3300,19 @@
           "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
           "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
           "dev": true,
           "requires": {
             "locate-path": "^2.0.0"
           }
         },
         "hosted-git-info": {
-          "version": "2.8.8",
-          "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
-          "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+          "version": "2.8.9",
+          "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+          "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
           "dev": true
         },
         "locate-path": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
           "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
           "dev": true,
           "requires": {
@@ -3476,19 +3482,19 @@
           "version": "1.3.0",
           "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
           "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
           "dev": true
         }
       }
     },
     "eslint-visitor-keys": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz",
-      "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+      "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
       "dev": true
     },
     "espree": {
       "version": "7.3.1",
       "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
       "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
       "dev": true,
       "requires": {
@@ -3845,19 +3851,19 @@
         },
         "get-stdin": {
           "version": "4.0.1",
           "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
           "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
           "dev": true
         },
         "hosted-git-info": {
-          "version": "2.8.8",
-          "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
-          "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+          "version": "2.8.9",
+          "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+          "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
           "dev": true
         },
         "indent-string": {
           "version": "2.1.0",
           "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
           "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
           "dev": true,
           "requires": {
@@ -4105,19 +4111,19 @@
       "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz",
       "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=",
       "dev": true,
       "requires": {
         "ini": "^1.3.2"
       }
     },
     "glob": {
-      "version": "7.1.6",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
-      "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+      "version": "7.1.7",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+      "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
       "requires": {
         "fs.realpath": "^1.0.0",
         "inflight": "^1.0.4",
         "inherits": "2",
         "minimatch": "^3.0.4",
         "once": "^1.3.0",
         "path-is-absolute": "^1.0.0"
       }
@@ -4153,19 +4159,19 @@
           "version": "0.8.1",
           "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
           "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
           "dev": true
         }
       }
     },
     "globby": {
-      "version": "11.0.2",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz",
-      "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==",
+      "version": "11.0.3",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz",
+      "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==",
       "dev": true,
       "requires": {
         "array-union": "^2.1.0",
         "dir-glob": "^3.0.1",
         "fast-glob": "^3.1.1",
         "ignore": "^5.1.4",
         "merge2": "^1.3.0",
         "slash": "^3.0.0"
@@ -4231,19 +4237,19 @@
     },
     "he": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
       "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
       "dev": true
     },
     "hosted-git-info": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.0.tgz",
-      "integrity": "sha512-fqhGdjk4av7mT9fU/B01dUtZ+WZSc/XEXMoLXDVZukiQRXxeHSSz3AqbeWRJHtF8EQYHlAgB1NSAHU0Cm7aqZA==",
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz",
+      "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==",
       "dev": true,
       "requires": {
         "lru-cache": "^6.0.0"
       }
     },
     "html-escaper": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
@@ -4485,64 +4491,64 @@
     },
     "is-arrayish": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
       "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
       "dev": true
     },
     "is-bigint": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz",
-      "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==",
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz",
+      "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==",
       "dev": true
     },
     "is-binary-path": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
       "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
       "dev": true,
       "requires": {
         "binary-extensions": "^2.0.0"
       }
     },
     "is-boolean-object": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz",
-      "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==",
-      "dev": true,
-      "requires": {
-        "call-bind": "^1.0.0"
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz",
+      "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==",
+      "dev": true,
+      "requires": {
+        "call-bind": "^1.0.2"
       }
     },
     "is-callable": {
       "version": "1.2.3",
       "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz",
       "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==",
       "dev": true
     },
     "is-core-module": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz",
-      "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==",
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
+      "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
       "dev": true,
       "requires": {
         "has": "^1.0.3"
       }
     },
     "is-date-object": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
-      "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz",
+      "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==",
       "dev": true
     },
     "is-docker": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz",
-      "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==",
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+      "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
       "dev": true
     },
     "is-extglob": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
       "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
       "dev": true
     },
@@ -4554,19 +4560,19 @@
     },
     "is-fullwidth-code-point": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
       "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
       "dev": true
     },
     "is-generator-function": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.8.tgz",
-      "integrity": "sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ==",
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz",
+      "integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A==",
       "dev": true
     },
     "is-glob": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
       "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
       "dev": true,
       "requires": {
@@ -4587,62 +4593,62 @@
     },
     "is-number": {
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
       "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
       "dev": true
     },
     "is-number-object": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz",
-      "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==",
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz",
+      "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==",
       "dev": true
     },
     "is-obj": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
       "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
       "dev": true
     },
     "is-plain-obj": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
       "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
       "dev": true
     },
     "is-regex": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz",
-      "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==",
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz",
+      "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==",
       "dev": true,
       "requires": {
         "call-bind": "^1.0.2",
-        "has-symbols": "^1.0.1"
+        "has-symbols": "^1.0.2"
       }
     },
     "is-stream": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
       "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
       "dev": true
     },
     "is-string": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
-      "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz",
+      "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==",
       "dev": true
     },
     "is-symbol": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
-      "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
-      "dev": true,
-      "requires": {
-        "has-symbols": "^1.0.1"
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+      "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+      "dev": true,
+      "requires": {
+        "has-symbols": "^1.0.2"
       }
     },
     "is-text-path": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz",
       "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=",
       "dev": true,
       "requires": {
@@ -4666,19 +4672,19 @@
     },
     "isarray": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
       "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
       "dev": true
     },
     "isbinaryfile": {
-      "version": "4.0.6",
-      "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.6.tgz",
-      "integrity": "sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg==",
+      "version": "4.0.8",
+      "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz",
+      "integrity": "sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==",
       "dev": true
     },
     "isexe": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
       "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
       "dev": true
     },
@@ -4882,19 +4888,19 @@
     },
     "jsonparse": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
       "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=",
       "dev": true
     },
     "just-extend": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz",
-      "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==",
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz",
+      "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==",
       "dev": true
     },
     "keygrip": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
       "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==",
       "dev": true,
       "requires": {
@@ -5104,16 +5110,22 @@
       "dev": true
     },
     "lodash.camelcase": {
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
       "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
       "dev": true
     },
+    "lodash.clonedeep": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+      "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
+      "dev": true
+    },
     "lodash.get": {
       "version": "4.4.2",
       "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
       "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
       "dev": true
     },
     "lodash.isequal": {
       "version": "4.5.0",
@@ -5122,20 +5134,20 @@
       "dev": true
     },
     "lodash.ismatch": {
       "version": "4.4.0",
       "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz",
       "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=",
       "dev": true
     },
-    "lodash.sortby": {
-      "version": "4.7.0",
-      "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
-      "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
+    "lodash.truncate": {
+      "version": "4.4.2",
+      "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
+      "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=",
       "dev": true
     },
     "lodash.zip": {
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz",
       "integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=",
       "dev": true
     },
@@ -5198,25 +5210,25 @@
     },
     "make-error": {
       "version": "1.3.6",
       "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
       "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
       "dev": true
     },
     "map-obj": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.2.0.tgz",
-      "integrity": "sha512-NAq0fCmZYGz9UFEQyndp7sisrow4GroyGeKluyKC/chuITZsPyOyC1UJZPJlVFImhXdROIP5xqouRLThT3BbpQ==",
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.2.1.tgz",
+      "integrity": "sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ==",
       "dev": true
     },
     "marky": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.1.tgz",
-      "integrity": "sha512-md9k+Gxa3qLH6sUKpeC2CNkJK/Ld+bEz5X96nYwloqphQE0CKCVEKco/6jxEZixinqNdz5RFi/KaCyfbMDMAXQ==",
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.2.tgz",
+      "integrity": "sha512-k1dB2HNeaNyORco8ulVEhctyEGkKHb2YWAhDsxeFlW2nROIirsctBYzKwwS3Vza+sKTS1zO4Z+n9/+9WbGLIxQ==",
       "dev": true
     },
     "mdurl": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
       "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
       "dev": true
     },
@@ -5247,44 +5259,44 @@
     },
     "merge2": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
       "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
       "dev": true
     },
     "micromatch": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
-      "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
+      "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
       "dev": true,
       "requires": {
         "braces": "^3.0.1",
-        "picomatch": "^2.0.5"
+        "picomatch": "^2.2.3"
       }
     },
     "mime": {
       "version": "2.5.2",
       "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz",
       "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==",
       "dev": true
     },
     "mime-db": {
-      "version": "1.46.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz",
-      "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==",
+      "version": "1.48.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz",
+      "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==",
       "dev": true
     },
     "mime-types": {
-      "version": "2.1.29",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz",
-      "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==",
-      "dev": true,
-      "requires": {
-        "mime-db": "1.46.0"
+      "version": "2.1.31",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz",
+      "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==",
+      "dev": true,
+      "requires": {
+        "mime-db": "1.48.0"
       }
     },
     "mimic-fn": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
       "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
       "dev": true
     },
@@ -5394,16 +5406,30 @@
           "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
           "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
           "dev": true,
           "requires": {
             "locate-path": "^6.0.0",
             "path-exists": "^4.0.0"
           }
         },
+        "glob": {
+          "version": "7.1.6",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+          "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+          "dev": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.4",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
         "js-yaml": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz",
           "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==",
           "dev": true,
           "requires": {
             "argparse": "^2.0.1"
           }
@@ -5457,19 +5483,19 @@
           "dev": true,
           "requires": {
             "ansi-styles": "^4.0.0",
             "string-width": "^4.1.0",
             "strip-ansi": "^6.0.0"
           }
         },
         "y18n": {
-          "version": "5.0.5",
-          "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz",
-          "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==",
+          "version": "5.0.8",
+          "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+          "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
           "dev": true
         },
         "yargs": {
           "version": "16.2.0",
           "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
           "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
           "dev": true,
           "requires": {
@@ -5551,31 +5577,42 @@
       }
     },
     "node-fetch": {
       "version": "2.6.1",
       "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
       "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
     },
     "node-releases": {
-      "version": "1.1.71",
-      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz",
-      "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==",
+      "version": "1.1.73",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz",
+      "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==",
       "dev": true
     },
     "normalize-package-data": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.1.tgz",
-      "integrity": "sha512-D/ttLdxo71msR4FF3VgSwK4blHfE3/vGByz1NCeE7/Dh8reQOKNJJjk5L10mLq9jxa+ZHzT1/HLgxljzbXE7Fw==",
-      "dev": true,
-      "requires": {
-        "hosted-git-info": "^4.0.0",
-        "resolve": "^1.17.0",
-        "semver": "^7.3.2",
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.2.tgz",
+      "integrity": "sha512-6CdZocmfGaKnIHPVFhJJZ3GuR8SsLKvDANFp47Jmy51aKIr8akjAWTSxtpI+MBgBFdSMRyo4hMpDlT6dTffgZg==",
+      "dev": true,
+      "requires": {
+        "hosted-git-info": "^4.0.1",
+        "resolve": "^1.20.0",
+        "semver": "^7.3.4",
         "validate-npm-package-license": "^3.0.1"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "7.3.5",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+          "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+          "dev": true,
+          "requires": {
+            "lru-cache": "^6.0.0"
+          }
+        }
       }
     },
     "normalize-path": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
       "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
       "dev": true
     },
@@ -5587,19 +5624,19 @@
     },
     "object-assign": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
       "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
       "dev": true
     },
     "object-inspect": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz",
-      "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==",
+      "version": "1.10.3",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz",
+      "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==",
       "dev": true
     },
     "object-keys": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
       "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
       "dev": true
     },
@@ -5611,25 +5648,24 @@
       "requires": {
         "call-bind": "^1.0.0",
         "define-properties": "^1.1.3",
         "has-symbols": "^1.0.1",
         "object-keys": "^1.1.1"
       }
     },
     "object.values": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz",
-      "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==",
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz",
+      "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==",
       "dev": true,
       "requires": {
         "call-bind": "^1.0.2",
         "define-properties": "^1.1.3",
-        "es-abstract": "^1.18.0-next.2",
-        "has": "^1.0.3"
+        "es-abstract": "^1.18.2"
       }
     },
     "on-finished": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
       "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
       "dev": true,
       "requires": {
@@ -5655,23 +5691,24 @@
     },
     "only": {
       "version": "0.0.2",
       "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz",
       "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=",
       "dev": true
     },
     "open": {
-      "version": "7.4.2",
-      "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
-      "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
-      "dev": true,
-      "requires": {
-        "is-docker": "^2.0.0",
-        "is-wsl": "^2.1.1"
+      "version": "8.2.0",
+      "resolved": "https://registry.npmjs.org/open/-/open-8.2.0.tgz",
+      "integrity": "sha512-O8uInONB4asyY3qUcEytpgwxQG3O0fJ/hlssoUHsBboOIRVZzT6Wq+Rwj5nffbeUhOdMjpXeISpDDzHCMRDuOQ==",
+      "dev": true,
+      "requires": {
+        "define-lazy-prop": "^2.0.0",
+        "is-docker": "^2.1.1",
+        "is-wsl": "^2.2.0"
       }
     },
     "opencollective-postinstall": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
       "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
       "dev": true
     },
@@ -5761,19 +5798,19 @@
     },
     "path-key": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
       "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
       "dev": true
     },
     "path-parse": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
-      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
       "dev": true
     },
     "path-to-regexp": {
       "version": "1.8.0",
       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
       "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
       "dev": true,
       "requires": {
@@ -5795,19 +5832,19 @@
       "dev": true
     },
     "pend": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
       "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
     },
     "picomatch": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
-      "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
+      "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
       "dev": true
     },
     "pify": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
       "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
       "dev": true
     },
@@ -6004,25 +6041,28 @@
     },
     "q": {
       "version": "1.5.1",
       "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
       "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=",
       "dev": true
     },
     "qs": {
-      "version": "6.9.6",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz",
-      "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==",
-      "dev": true
+      "version": "6.10.1",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz",
+      "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
+      "dev": true,
+      "requires": {
+        "side-channel": "^1.0.4"
+      }
     },
     "queue-microtask": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz",
-      "integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==",
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
       "dev": true
     },
     "quick-lru": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
       "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
       "dev": true
     },
@@ -6088,19 +6128,19 @@
       "requires": {
         "@types/normalize-package-data": "^2.4.0",
         "normalize-package-data": "^2.5.0",
         "parse-json": "^5.0.0",
         "type-fest": "^0.6.0"
       },
       "dependencies": {
         "hosted-git-info": {
-          "version": "2.8.8",
-          "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
-          "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+          "version": "2.8.9",
+          "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+          "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
           "dev": true
         },
         "normalize-package-data": {
           "version": "2.5.0",
           "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
           "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
           "dev": true,
           "requires": {
@@ -6325,19 +6365,19 @@
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
       "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
       "requires": {
         "glob": "^7.1.3"
       }
     },
     "rollup": {
-      "version": "2.41.1",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.41.1.tgz",
-      "integrity": "sha512-nepLFAW5W71/MWpS2Yr7r31eS7HRfYg2RXnxb6ehqN9zY42yACxKtEfb4xq8SmNfUohAzGMcyl6jkwdLOAiUbg==",
+      "version": "2.51.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.51.1.tgz",
+      "integrity": "sha512-8xfDbAtBleXotb6qKEHWuo/jkn94a9dVqGc7Rwl3sqspCVlnCfbRek7ldhCARSi7h32H0xR4QThm1t9zHN+3uw==",
       "dev": true,
       "requires": {
         "fsevents": "~2.3.1"
       }
     },
     "run-parallel": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -6427,16 +6467,27 @@
       "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==",
       "dev": true,
       "requires": {
         "glob": "^7.0.0",
         "interpret": "^1.0.0",
         "rechoir": "^0.6.2"
       }
     },
+    "side-channel": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+      "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+      "dev": true,
+      "requires": {
+        "call-bind": "^1.0.0",
+        "get-intrinsic": "^1.0.2",
+        "object-inspect": "^1.9.0"
+      }
+    },
     "signal-exit": {
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
       "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
       "dev": true
     },
     "sinon": {
       "version": "9.2.4",
@@ -6515,19 +6566,19 @@
       "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
       "dev": true,
       "requires": {
         "spdx-exceptions": "^2.1.0",
         "spdx-license-ids": "^3.0.0"
       }
     },
     "spdx-license-ids": {
-      "version": "3.0.7",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz",
-      "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==",
+      "version": "3.0.9",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz",
+      "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==",
       "dev": true
     },
     "split": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
       "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
       "dev": true,
       "requires": {
@@ -6545,19 +6596,19 @@
     },
     "sprintf-js": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
       "dev": true
     },
     "stack-utils": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.4.tgz",
-      "integrity": "sha512-IPDJfugEGbfizBwBZRZ3xpccMdRyP5lqsBWXGQWimVjua/ccLCeMOAVjlc1R7LxFjo5sEDhyNIXd8mo/AiDS9w==",
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.5.tgz",
+      "integrity": "sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ==",
       "dev": true,
       "requires": {
         "escape-string-regexp": "^2.0.0"
       },
       "dependencies": {
         "escape-string-regexp": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
@@ -6630,16 +6681,27 @@
           }
         },
         "color-name": {
           "version": "1.1.3",
           "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
           "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
           "dev": true
         },
+        "conventional-changelog-conventionalcommits": {
+          "version": "4.5.0",
+          "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.5.0.tgz",
+          "integrity": "sha512-buge9xDvjjOxJlyxUnar/+6i/aVEVGA7EEh4OafBCXPlLUQPGbRUBhBUveWRxzvR8TEjhKEP4BdepnpG2FSZXw==",
+          "dev": true,
+          "requires": {
+            "compare-func": "^2.0.0",
+            "lodash": "^4.17.15",
+            "q": "^1.5.1"
+          }
+        },
         "find-up": {
           "version": "5.0.0",
           "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
           "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
           "dev": true,
           "requires": {
             "locate-path": "^6.0.0",
             "path-exists": "^4.0.0"
@@ -6720,19 +6782,19 @@
               "version": "1.1.4",
               "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
               "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
               "dev": true
             }
           }
         },
         "y18n": {
-          "version": "5.0.5",
-          "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz",
-          "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==",
+          "version": "5.0.8",
+          "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+          "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
           "dev": true
         },
         "yargs": {
           "version": "16.2.0",
           "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
           "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
           "dev": true,
           "requires": {
@@ -6845,31 +6907,33 @@
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
       "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
       "dev": true,
       "requires": {
         "has-flag": "^4.0.0"
       }
     },
     "table": {
-      "version": "6.0.7",
-      "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz",
-      "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==",
-      "dev": true,
-      "requires": {
-        "ajv": "^7.0.2",
-        "lodash": "^4.17.20",
+      "version": "6.7.1",
+      "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz",
+      "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==",
+      "dev": true,
+      "requires": {
+        "ajv": "^8.0.1",
+        "lodash.clonedeep": "^4.5.0",
+        "lodash.truncate": "^4.4.2",
         "slice-ansi": "^4.0.0",
-        "string-width": "^4.2.0"
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0"
       },
       "dependencies": {
         "ajv": {
-          "version": "7.2.1",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.2.1.tgz",
-          "integrity": "sha512-+nu0HDv7kNSOua9apAVc979qd932rrZeb3WOvoiD31A/p1mIE5/9bN2027pE2rOPYEdS3UHzsvof4hY+lM9/WQ==",
+          "version": "8.6.0",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.0.tgz",
+          "integrity": "sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==",
           "dev": true,
           "requires": {
             "fast-deep-equal": "^3.1.1",
             "json-schema-traverse": "^1.0.0",
             "require-from-string": "^2.0.2",
             "uri-js": "^4.2.2"
           }
         },
@@ -6889,19 +6953,19 @@
       "requires": {
         "array-back": "^4.0.1",
         "deep-extend": "~0.6.0",
         "typical": "^5.2.0",
         "wordwrapjs": "^4.0.0"
       },
       "dependencies": {
         "array-back": {
-          "version": "4.0.1",
-          "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz",
-          "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==",
+          "version": "4.0.2",
+          "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz",
+          "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==",
           "dev": true
         },
         "typical": {
           "version": "5.2.0",
           "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz",
           "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==",
           "dev": true
         }
@@ -6985,28 +7049,28 @@
     },
     "toidentifier": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
       "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
       "dev": true
     },
     "tr46": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz",
-      "integrity": "sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz",
+      "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==",
       "dev": true,
       "requires": {
         "punycode": "^2.1.1"
       }
     },
     "trim-newlines": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz",
-      "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==",
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
+      "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
       "dev": true
     },
     "trim-off-newlines": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz",
       "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=",
       "dev": true
     },
@@ -7110,32 +7174,32 @@
     },
     "typical": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz",
       "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==",
       "dev": true
     },
     "uglify-js": {
-      "version": "3.13.0",
-      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.0.tgz",
-      "integrity": "sha512-TWYSWa9T2pPN4DIJYbU9oAjQx+5qdV5RUDxwARg8fmJZrD/V27Zj0JngW5xg1DFz42G0uDYl2XhzF6alSzD62w==",
+      "version": "3.13.9",
+      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.9.tgz",
+      "integrity": "sha512-wZbyTQ1w6Y7fHdt8sJnHfSIuWeDgk6B5rCb4E/AM6QNNPbOMIZph21PW5dRB3h7Df0GszN+t7RuUH6sWK5bF0g==",
       "dev": true,
       "optional": true
     },
     "unbox-primitive": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.0.tgz",
-      "integrity": "sha512-P/51NX+JXyxK/aigg1/ZgyccdAxm5K1+n8+tvqSntjOivPt19gvm1VC49RWYetsiub8WViUchdxl/KWHHB0kzA==",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
+      "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
       "dev": true,
       "requires": {
         "function-bind": "^1.1.1",
-        "has-bigints": "^1.0.0",
-        "has-symbols": "^1.0.0",
-        "which-boxed-primitive": "^1.0.1"
+        "has-bigints": "^1.0.1",
+        "has-symbols": "^1.0.2",
+        "which-boxed-primitive": "^1.0.2"
       }
     },
     "unbzip2-stream": {
       "version": "1.4.3",
       "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
       "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
       "requires": {
         "buffer": "^5.2.1",
@@ -7176,19 +7240,19 @@
     },
     "v8-compile-cache": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
       "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
       "dev": true
     },
     "v8-to-istanbul": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.0.tgz",
-      "integrity": "sha512-uXUVqNUCLa0AH1vuVxzi+MI4RfxEOKt9pBgKwHbgH7st8Kv2P1m+jvWNnektzBh5QShF3ODgKmUFCf38LnVz1g==",
+      "version": "7.1.2",
+      "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz",
+      "integrity": "sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==",
       "dev": true,
       "requires": {
         "@types/istanbul-lib-coverage": "^2.0.1",
         "convert-source-map": "^1.6.0",
         "source-map": "^0.7.3"
       },
       "dependencies": {
         "source-map": {
@@ -7223,23 +7287,23 @@
     },
     "webidl-conversions": {
       "version": "6.1.0",
       "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz",
       "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==",
       "dev": true
     },
     "whatwg-url": {
-      "version": "8.4.0",
-      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.4.0.tgz",
-      "integrity": "sha512-vwTUFf6V4zhcPkWp/4CQPr1TW9Ml6SF4lVyaIMBdJw5i6qUUJ1QWM4Z6YYVkfka0OUIzVo/0aNtGVGk256IKWw==",
-      "dev": true,
-      "requires": {
-        "lodash.sortby": "^4.7.0",
-        "tr46": "^2.0.2",
+      "version": "8.6.0",
+      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.6.0.tgz",
+      "integrity": "sha512-os0KkeeqUOl7ccdDT1qqUcS4KH4tcBTSKK5Nl5WKb2lyxInIZ/CpjkqKa1Ss12mjfdcRX9mHmPPs7/SxG1Hbdw==",
+      "dev": true,
+      "requires": {
+        "lodash": "^4.7.0",
+        "tr46": "^2.1.0",
         "webidl-conversions": "^6.1.0"
       }
     },
     "which": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
       "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
       "dev": true,
@@ -7322,23 +7386,23 @@
     },
     "wordwrap": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
       "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
       "dev": true
     },
     "wordwrapjs": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.0.tgz",
-      "integrity": "sha512-Svqw723a3R34KvsMgpjFBYCgNOSdcW3mQFK4wIfhGQhtaFVOJmdYoXgi63ne3dTlWgatVcUc7t4HtQ/+bUVIzQ==",
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz",
+      "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==",
       "dev": true,
       "requires": {
         "reduce-flatten": "^2.0.0",
-        "typical": "^5.0.0"
+        "typical": "^5.2.0"
       },
       "dependencies": {
         "typical": {
           "version": "5.2.0",
           "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz",
           "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==",
           "dev": true
         }
@@ -7373,31 +7437,31 @@
     },
     "xtend": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
       "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
       "dev": true
     },
     "y18n": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
-      "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
       "dev": true
     },
     "yallist": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
       "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
       "dev": true
     },
     "yaml": {
-      "version": "1.10.0",
-      "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz",
-      "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==",
+      "version": "1.10.2",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+      "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
       "dev": true
     },
     "yargs": {
       "version": "15.4.1",
       "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
       "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
       "dev": true,
       "requires": {
--- a/remote/test/puppeteer/package.json
+++ b/remote/test/puppeteer/package.json
@@ -1,11 +1,11 @@
 {
   "name": "puppeteer",
-  "version": "8.0.0",
+  "version": "9.1.1",
   "description": "A high-level API to control headless Chrome over the DevTools Protocol",
   "main": "./cjs-entry.js",
   "types": "lib/types.d.ts",
   "repository": "github:puppeteer/puppeteer",
   "engines": {
     "node": ">=10.18.1"
   },
   "scripts": {
@@ -19,19 +19,21 @@
     "test": "npm run tsc && npm run lint --silent && npm run unit-with-coverage && npm run test-browser",
     "prepare": "node typescript-if-required.js",
     "prepublishOnly": "npm run build",
     "dev-install": "npm run tsc && node install.js",
     "install": "node install.js",
     "eslint": "([ \"$CI\" = true ] && eslint --ext js --ext ts --quiet -f codeframe . || eslint --ext js --ext ts .)",
     "eslint-fix": "eslint --ext js --ext ts --fix .",
     "commitlint": "commitlint --from=HEAD~1",
-    "lint": "npm run eslint && npm run build && npm run doc && npm run commitlint",
+    "markdownlint": "prettier --check **/README.md docs/api.md docs/troubleshooting.md",
+    "markdownlint-fix": "prettier --write **/README.md docs/api.md docs/troubleshooting.md",
+    "lint": "npm run eslint && npm run build && npm run doc && npm run commitlint && npm run markdownlint",
     "doc": "node utils/doclint/cli.js",
-    "clean-lib": "rm -rf lib",
+    "clean-lib": "rimraf lib",
     "build": "npm run tsc && npm run generate-d-ts",
     "tsc": "npm run clean-lib && tsc --version && npm run tsc-cjs && npm run tsc-esm",
     "tsc-cjs": "tsc -b src/tsconfig.cjs.json",
     "tsc-esm": "tsc -b src/tsconfig.esm.json",
     "apply-next-version": "node utils/apply_next_version.js",
     "test-install": "scripts/test-install.sh",
     "generate-d-ts": "api-extractor run --local --verbose",
     "generate-docs": "npm run generate-d-ts && api-documenter markdown -i temp -o new-docs",
@@ -48,70 +50,70 @@
     "install.js",
     "typescript-if-required.js",
     "cjs-entry.js",
     "cjs-entry-core.js"
   ],
   "author": "The Chromium Authors",
   "license": "Apache-2.0",
   "dependencies": {
-    "debug": "^4.1.0",
-    "devtools-protocol": "0.0.854822",
-    "extract-zip": "^2.0.0",
-    "https-proxy-agent": "^5.0.0",
-    "node-fetch": "^2.6.1",
-    "pkg-dir": "^4.2.0",
-    "progress": "^2.0.1",
-    "proxy-from-env": "^1.1.0",
-    "rimraf": "^3.0.2",
-    "tar-fs": "^2.0.0",
-    "unbzip2-stream": "^1.3.3",
-    "ws": "^7.2.3"
+    "debug": "4.3.1",
+    "devtools-protocol": "0.0.869402",
+    "extract-zip": "2.0.1",
+    "https-proxy-agent": "5.0.0",
+    "node-fetch": "2.6.1",
+    "pkg-dir": "4.2.0",
+    "progress": "2.0.3",
+    "proxy-from-env": "1.1.0",
+    "rimraf": "3.0.2",
+    "tar-fs": "2.1.1",
+    "unbzip2-stream": "1.4.3",
+    "ws": "7.4.4"
   },
   "devDependencies": {
-    "@commitlint/cli": "^11.0.0",
-    "@commitlint/config-conventional": "^11.0.0",
-    "@microsoft/api-documenter": "^7.12.7",
-    "@microsoft/api-extractor": "^7.13.1",
+    "@commitlint/cli": "11.0.0",
+    "@commitlint/config-conventional": "11.0.0",
+    "@microsoft/api-documenter": "7.12.11",
+    "@microsoft/api-extractor": "7.13.2",
     "@types/debug": "0.0.31",
-    "@types/mime": "^2.0.0",
-    "@types/mocha": "^7.0.2",
-    "@types/node": "^14.0.13",
-    "@types/proxy-from-env": "^1.0.1",
-    "@types/rimraf": "^2.0.2",
-    "@types/sinon": "^9.0.4",
-    "@types/tar-fs": "^1.16.2",
-    "@types/ws": "^7.2.4",
-    "@typescript-eslint/eslint-plugin": "^4.4.0",
-    "@typescript-eslint/parser": "^4.4.0",
-    "@web/test-runner": "^0.12.15",
-    "commonmark": "^0.28.1",
-    "cross-env": "^7.0.2",
-    "eslint": "^7.10.0",
-    "eslint-config-prettier": "^6.12.0",
-    "eslint-plugin-import": "^2.22.0",
-    "eslint-plugin-mocha": "^8.0.0",
-    "eslint-plugin-prettier": "^3.1.4",
-    "eslint-plugin-unicorn": "^22.0.0",
-    "esprima": "^4.0.0",
-    "expect": "^25.2.7",
-    "husky": "^4.3.0",
-    "jpeg-js": "^0.3.7",
-    "mime": "^2.0.3",
-    "minimist": "^1.2.0",
-    "mocha": "^8.2.0",
-    "ncp": "^2.0.0",
-    "pixelmatch": "^4.0.2",
-    "pngjs": "^5.0.0",
-    "prettier": "^2.1.2",
-    "sinon": "^9.0.2",
-    "source-map-support": "^0.5.19",
-    "standard-version": "^9.0.0",
-    "text-diff": "^1.0.1",
-    "ts-node": "^9.0.0",
-    "typescript": "^4.1.5"
+    "@types/mime": "2.0.3",
+    "@types/mocha": "7.0.2",
+    "@types/node": "14.14.33",
+    "@types/proxy-from-env": "1.0.1",
+    "@types/rimraf": "2.0.4",
+    "@types/sinon": "9.0.11",
+    "@types/tar-fs": "1.16.3",
+    "@types/ws": "7.4.0",
+    "@typescript-eslint/eslint-plugin": "4.17.0",
+    "@typescript-eslint/parser": "4.17.0",
+    "@web/test-runner": "0.12.16",
+    "commonmark": "0.28.1",
+    "cross-env": "7.0.3",
+    "eslint": "7.21.0",
+    "eslint-config-prettier": "6.15.0",
+    "eslint-plugin-import": "2.22.1",
+    "eslint-plugin-mocha": "8.1.0",
+    "eslint-plugin-prettier": "3.3.1",
+    "eslint-plugin-unicorn": "22.0.0",
+    "esprima": "4.0.1",
+    "expect": "25.5.0",
+    "husky": "4.3.8",
+    "jpeg-js": "0.3.7",
+    "mime": "2.5.2",
+    "minimist": "1.2.5",
+    "mocha": "8.3.1",
+    "ncp": "2.0.0",
+    "pixelmatch": "4.0.2",
+    "pngjs": "5.0.0",
+    "prettier": "2.2.1",
+    "sinon": "9.2.4",
+    "source-map-support": "0.5.19",
+    "standard-version": "9.1.1",
+    "text-diff": "1.0.1",
+    "ts-node": "9.1.1",
+    "typescript": "4.2.3"
   },
   "husky": {
     "hooks": {
       "commit-msg": "commitlint --env HUSKY_GIT_PARAMS"
     }
   }
 }
--- a/remote/test/puppeteer/scripts/test-ts-definition-files.ts
+++ b/remote/test/puppeteer/scripts/test-ts-definition-files.ts
@@ -29,44 +29,44 @@ const EXPECTED_ERRORS = new Map<string, 
     ],
   ],
   [
     'js-esm-import-cjs-output',
     [
       "bad.js(5,35): error TS2551: Property 'launh' does not exist on type",
       "bad.js(7,29): error TS2551: Property 'devics' does not exist on type",
       'bad.js(11,39): error TS2554: Expected 0 arguments, but got 1.',
-      "bad.js(15,9): error TS2322: Type 'ElementHandle<Element> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
+      "bad.js(15,9): error TS2322: Type 'ElementHandle<HTMLElement> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
     ],
   ],
   [
     'js-cjs-import-esm-output',
     [
       "bad.js(5,35): error TS2551: Property 'launh' does not exist on type",
       "bad.js(7,29): error TS2551: Property 'devics' does not exist on type",
       'bad.js(11,39): error TS2554: Expected 0 arguments, but got 1.',
-      "bad.js(15,9): error TS2322: Type 'ElementHandle<Element> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
+      "bad.js(15,9): error TS2322: Type 'ElementHandle<HTMLElement> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
     ],
   ],
   [
     'js-esm-import-esm-output',
     [
       "bad.js(5,35): error TS2551: Property 'launh' does not exist on type",
       "bad.js(7,29): error TS2551: Property 'devics' does not exist on type",
       'bad.js(11,39): error TS2554: Expected 0 arguments, but got 1.',
-      "bad.js(15,9): error TS2322: Type 'ElementHandle<Element> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
+      "bad.js(15,9): error TS2322: Type 'ElementHandle<HTMLElement> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
     ],
   ],
   [
     'js-cjs-import-cjs-output',
     [
       "bad.js(5,35): error TS2551: Property 'launh' does not exist on type",
       "bad.js(7,29): error TS2551: Property 'devics' does not exist on type",
       'bad.js(11,39): error TS2554: Expected 0 arguments, but got 1.',
-      "bad.js(15,9): error TS2322: Type 'ElementHandle<Element> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
+      "bad.js(15,9): error TS2322: Type 'ElementHandle<HTMLElement> | null' is not assignable to type 'ElementHandle<HTMLElement>'",
     ],
   ],
 ]);
 const PROJECT_FOLDERS = [...EXPECTED_ERRORS.keys()];
 
 function packPuppeteer() {
   console.log('Packing Puppeteer');
   const result = spawnSync('npm', ['pack'], {
--- a/remote/test/puppeteer/src/common/AriaQueryHandler.ts
+++ b/remote/test/puppeteer/src/common/AriaQueryHandler.ts
@@ -47,25 +47,23 @@ async function queryAXTree(
  * - 'label' queries for elements with name 'label' and any role.
  * - '[name=""][role="button"]' queries for elements with no name and role 'button'.
  */
 type ariaQueryOption = { name?: string; role?: string };
 function parseAriaSelector(selector: string): ariaQueryOption {
   const normalize = (value: string): string => value.replace(/ +/g, ' ').trim();
   const knownAttributes = new Set(['name', 'role']);
   const queryOptions: ariaQueryOption = {};
-  const attributeRegexp = /\[\s*(?<attribute>\w+)\s*=\s*"(?<value>\\.|[^"\\]*)"\s*\]/;
+  const attributeRegexp = /\[\s*(?<attribute>\w+)\s*=\s*"(?<value>\\.|[^"\\]*)"\s*\]/g;
   const defaultName = selector.replace(
     attributeRegexp,
     (_, attribute: string, value: string) => {
       attribute = attribute.trim();
       if (!knownAttributes.has(attribute))
-        throw new Error(
-          'Unkown aria attribute "${groups.attribute}" in selector'
-        );
+        throw new Error(`Unknown aria attribute "${attribute}" in selector`);
       queryOptions[attribute] = normalize(value);
       return '';
     }
   );
   if (defaultName && !queryOptions.name)
     queryOptions.name = normalize(defaultName);
   return queryOptions;
 }
--- a/remote/test/puppeteer/src/common/Browser.ts
+++ b/remote/test/puppeteer/src/common/Browser.ts
@@ -19,17 +19,27 @@ import { helper } from './helper.js';
 import { Target } from './Target.js';
 import { EventEmitter } from './EventEmitter.js';
 import { Connection, ConnectionEmittedEvents } from './Connection.js';
 import { Protocol } from 'devtools-protocol';
 import { Page } from './Page.js';
 import { ChildProcess } from 'child_process';
 import { Viewport } from './PuppeteerViewport.js';
 
-type BrowserCloseCallback = () => Promise<void> | void;
+/**
+ * @internal
+ */
+export type BrowserCloseCallback = () => Promise<void> | void;
+
+/**
+ * @public
+ */
+export type TargetFilterCallback = (
+  target: Protocol.Target.TargetInfo
+) => boolean;
 
 const WEB_PERMISSION_TO_PROTOCOL_PERMISSION = new Map<
   Permission,
   Protocol.Browser.PermissionType
 >([
   ['geolocation', 'geolocation'],
   ['midi', 'midi'],
   ['notifications', 'notifications'],
@@ -179,61 +189,66 @@ export const enum BrowserEmittedEvents {
 export class Browser extends EventEmitter {
   /**
    * @internal
    */
   static async create(
     connection: Connection,
     contextIds: string[],
     ignoreHTTPSErrors: boolean,
-    defaultViewport?: Viewport,
+    defaultViewport?: Viewport | null,
     process?: ChildProcess,
-    closeCallback?: BrowserCloseCallback
+    closeCallback?: BrowserCloseCallback,
+    targetFilterCallback?: TargetFilterCallback
   ): Promise<Browser> {
     const browser = new Browser(
       connection,
       contextIds,
       ignoreHTTPSErrors,
       defaultViewport,
       process,
-      closeCallback
+      closeCallback,
+      targetFilterCallback
     );
     await connection.send('Target.setDiscoverTargets', { discover: true });
     return browser;
   }
   private _ignoreHTTPSErrors: boolean;
-  private _defaultViewport?: Viewport;
+  private _defaultViewport?: Viewport | null;
   private _process?: ChildProcess;
   private _connection: Connection;
   private _closeCallback: BrowserCloseCallback;
+  private _targetFilterCallback: TargetFilterCallback;
   private _defaultContext: BrowserContext;
   private _contexts: Map<string, BrowserContext>;
   /**
    * @internal
    * Used in Target.ts directly so cannot be marked private.
    */
   _targets: Map<string, Target>;
 
   /**
    * @internal
    */
   constructor(
     connection: Connection,
     contextIds: string[],
     ignoreHTTPSErrors: boolean,
-    defaultViewport?: Viewport,
+    defaultViewport?: Viewport | null,
     process?: ChildProcess,
-    closeCallback?: BrowserCloseCallback
+    closeCallback?: BrowserCloseCallback,
+    targetFilterCallback?: TargetFilterCallback
   ) {
     super();
     this._ignoreHTTPSErrors = ignoreHTTPSErrors;
     this._defaultViewport = defaultViewport;
     this._process = process;
     this._connection = connection;
     this._closeCallback = closeCallback || function (): void {};
+    this._targetFilterCallback = targetFilterCallback || ((): boolean => true);
 
     this._defaultContext = new BrowserContext(this._connection, this, null);
     this._contexts = new Map();
     for (const contextId of contextIds)
       this._contexts.set(
         contextId,
         new BrowserContext(this._connection, this, contextId)
       );
@@ -322,16 +337,21 @@ export class Browser extends EventEmitte
   ): Promise<void> {
     const targetInfo = event.targetInfo;
     const { browserContextId } = targetInfo;
     const context =
       browserContextId && this._contexts.has(browserContextId)
         ? this._contexts.get(browserContextId)
         : this._defaultContext;
 
+    const shouldAttachToTarget = this._targetFilterCallback(targetInfo);
+    if (!shouldAttachToTarget) {
+      return;
+    }
+
     const target = new Target(
       targetInfo,
       context,
       () => this._connection.createSession(targetInfo),
       this._ignoreHTTPSErrors,
       this._defaultViewport
     );
     assert(
@@ -545,17 +565,19 @@ export class Browser extends EventEmitte
   isConnected(): boolean {
     return !this._connection._closed;
   }
 
   private _getVersion(): Promise<Protocol.Browser.GetVersionResponse> {
     return this._connection.send('Browser.getVersion');
   }
 }
-
+/**
+ * @public
+ */
 export const enum BrowserContextEmittedEvents {
   /**
    * Emitted when the url of a target inside the browser context changes.
    * Contains a {@link Target} instance.
    */
   TargetChanged = 'targetchanged',
 
   /**
@@ -599,16 +621,17 @@ export const enum BrowserContextEmittedE
  * const context = await browser.createIncognitoBrowserContext();
  * // Create a new page inside context.
  * const page = await context.newPage();
  * // ... do stuff with page ...
  * await page.goto('https://example.com');
  * // Dispose context once it's no longer needed.
  * await context.close();
  * ```
+ * @public
  */
 export class BrowserContext extends EventEmitter {
   private _connection: Connection;
   private _browser: Browser;
   private _id?: string;
 
   /**
    * @internal
--- a/remote/test/puppeteer/src/common/BrowserConnector.ts
+++ b/remote/test/puppeteer/src/common/BrowserConnector.ts
@@ -10,17 +10,17 @@
  * 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.
  */
 
 import { ConnectionTransport } from './ConnectionTransport.js';
-import { Browser } from './Browser.js';
+import { Browser, TargetFilterCallback } from './Browser.js';
 import { assert } from './assert.js';
 import { debugError } from '../common/helper.js';
 import { Connection } from './Connection.js';
 import { getFetch } from './fetch.js';
 import { Viewport } from './PuppeteerViewport.js';
 import { isNode } from '../environment.js';
 
 /**
@@ -32,22 +32,26 @@ export interface BrowserConnectOptions {
   /**
    * Whether to ignore HTTPS errors during navigation.
    * @defaultValue false
    */
   ignoreHTTPSErrors?: boolean;
   /**
    * Sets the viewport for each page.
    */
-  defaultViewport?: Viewport;
+  defaultViewport?: Viewport | null;
   /**
    * Slows down Puppeteer operations by the specified amount of milliseconds to
    * aid debugging.
    */
   slowMo?: number;
+  /**
+   * Callback to decide if Puppeteer should connect to a given target or not.
+   */
+  targetFilter?: TargetFilterCallback;
 }
 
 const getWebSocketTransportClass = async () => {
   return isNode
     ? (await import('../node/NodeWebSocketTransport.js')).NodeWebSocketTransport
     : (await import('./BrowserWebSocketTransport.js'))
         .BrowserWebSocketTransport;
 };
@@ -66,16 +70,17 @@ export const connectToBrowser = async (
 ): Promise<Browser> => {
   const {
     browserWSEndpoint,
     browserURL,
     ignoreHTTPSErrors = false,
     defaultViewport = { width: 800, height: 600 },
     transport,
     slowMo = 0,
+    targetFilter,
   } = options;
 
   assert(
     Number(!!browserWSEndpoint) + Number(!!browserURL) + Number(!!transport) ===
       1,
     'Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect'
   );
 
@@ -101,17 +106,18 @@ export const connectToBrowser = async (
     'Target.getBrowserContexts'
   );
   return Browser.create(
     connection,
     browserContextIds,
     ignoreHTTPSErrors,
     defaultViewport,
     null,
-    () => connection.send('Browser.close').catch(debugError)
+    () => connection.send('Browser.close').catch(debugError),
+    targetFilter
   );
 };
 
 async function getWSEndpoint(browserURL: string): Promise<string> {
   const endpointURL = new URL('/json/version', browserURL);
 
   const fetch = await getFetch();
   try {
--- a/remote/test/puppeteer/src/common/Connection.ts
+++ b/remote/test/puppeteer/src/common/Connection.ts
@@ -18,17 +18,25 @@ import { debug } from './Debug.js';
 const debugProtocolSend = debug('puppeteer:protocol:SEND ►');
 const debugProtocolReceive = debug('puppeteer:protocol:RECV ◀');
 
 import { Protocol } from 'devtools-protocol';
 import { ProtocolMapping } from 'devtools-protocol/types/protocol-mapping.js';
 import { ConnectionTransport } from './ConnectionTransport.js';
 import { EventEmitter } from './EventEmitter.js';
 
-interface ConnectionCallback {
+/**
+ * @public
+ */
+export { ConnectionTransport, ProtocolMapping };
+
+/**
+ * @public
+ */
+export interface ConnectionCallback {
   resolve: Function;
   reject: Function;
   error: Error;
   method: string;
 }
 
 /**
  * Internal events that the Connection class emits.
@@ -62,18 +70,18 @@ export class Connection extends EventEmi
     this._transport.onclose = this._onClose.bind(this);
   }
 
   static fromSession(session: CDPSession): Connection {
     return session._connection;
   }
 
   /**
-   * @param {string} sessionId
-   * @returns {?CDPSession}
+   * @param sessionId - The session id
+   * @returns The current CDP session if it exists
    */
   session(sessionId: string): CDPSession | null {
     return this._sessions.get(sessionId) || null;
   }
 
   url(): string {
     return this._url;
   }
@@ -162,31 +170,34 @@ export class Connection extends EventEmi
   }
 
   dispose(): void {
     this._onClose();
     this._transport.close();
   }
 
   /**
-   * @param {Protocol.Target.TargetInfo} targetInfo
-   * @returns {!Promise<!CDPSession>}
+   * @param targetInfo - The target info
+   * @returns The CDP session that is created
    */
   async createSession(
     targetInfo: Protocol.Target.TargetInfo
   ): Promise<CDPSession> {
     const { sessionId } = await this.send('Target.attachToTarget', {
       targetId: targetInfo.targetId,
       flatten: true,
     });
     return this._sessions.get(sessionId);
   }
 }
 
-interface CDPSessionOnMessageObject {
+/**
+ * @public
+ */
+export interface CDPSessionOnMessageObject {
   id?: number;
   method: string;
   params: Record<string, unknown>;
   error: { message: string; data: any };
   result?: any;
 }
 
 /**
--- a/remote/test/puppeteer/src/common/ConnectionTransport.ts
+++ b/remote/test/puppeteer/src/common/ConnectionTransport.ts
@@ -9,14 +9,17 @@
  *
  * 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.
  */
 
+/**
+ * @public
+ */
 export interface ConnectionTransport {
   send(string);
   close();
   onmessage?: (message: string) => void;
   onclose?: () => void;
 }
--- a/remote/test/puppeteer/src/common/ConsoleMessage.ts
+++ b/remote/test/puppeteer/src/common/ConsoleMessage.ts
@@ -33,16 +33,17 @@ export interface ConsoleMessageLocation 
   /**
    * 0-based column number in the resource if known or `undefined` otherwise.
    */
   columnNumber?: number;
 }
 
 /**
  * The supported types for console messages.
+ * @public
  */
 export type ConsoleMessageType =
   | 'log'
   | 'debug'
   | 'info'
   | 'error'
   | 'warning'
   | 'dir'
--- a/remote/test/puppeteer/src/common/Coverage.ts
+++ b/remote/test/puppeteer/src/common/Coverage.ts
@@ -17,16 +17,21 @@
 import { assert } from './assert.js';
 import { helper, debugError, PuppeteerEventListener } from './helper.js';
 import { Protocol } from 'devtools-protocol';
 import { CDPSession } from './Connection.js';
 
 import { EVALUATION_SCRIPT_URL } from './ExecutionContext.js';
 
 /**
+ * @internal
+ */
+export { PuppeteerEventListener };
+
+/**
  * The CoverageEntry class represents one entry of the coverage report.
  * @public
  */
 export interface CoverageEntry {
   /**
    * The URL of the style sheet or script.
    */
   url: string;
@@ -159,17 +164,20 @@ export class Coverage {
    * CSS Coverage doesn't include dynamically injected style tags
    * without sourceURLs.
    */
   async stopCSSCoverage(): Promise<CoverageEntry[]> {
     return await this._cssCoverage.stop();
   }
 }
 
-class JSCoverage {
+/**
+ * @public
+ */
+export class JSCoverage {
   _client: CDPSession;
   _enabled = false;
   _scriptURLs = new Map<string, string>();
   _scriptSources = new Map<string, string>();
   _eventListeners: PuppeteerEventListener[] = [];
   _resetOnNavigation = false;
   _reportAnonymousScripts = false;
 
@@ -272,17 +280,20 @@ class JSCoverage {
       for (const func of entry.functions) flattenRanges.push(...func.ranges);
       const ranges = convertToDisjointRanges(flattenRanges);
       coverage.push({ url, ranges, text });
     }
     return coverage;
   }
 }
 
-class CSSCoverage {
+/**
+ * @public
+ */
+export class CSSCoverage {
   _client: CDPSession;
   _enabled = false;
   _stylesheetURLs = new Map<string, string>();
   _stylesheetSources = new Map<string, string>();
   _eventListeners: PuppeteerEventListener[] = [];
   _resetOnNavigation = false;
   _reportAnonymousScripts = false;
 
--- a/remote/test/puppeteer/src/common/DOMWorld.ts
+++ b/remote/test/puppeteer/src/common/DOMWorld.ts
@@ -161,19 +161,21 @@ export class DOMWorld {
   ): Promise<UnwrapPromiseLike<EvaluateFnReturnType<T>>> {
     const context = await this.executionContext();
     return context.evaluate<UnwrapPromiseLike<EvaluateFnReturnType<T>>>(
       pageFunction,
       ...args
     );
   }
 
-  async $(selector: string): Promise<ElementHandle | null> {
+  async $<T extends Element = Element>(
+    selector: string
+  ): Promise<ElementHandle<T> | null> {
     const document = await this._document();
-    const value = await document.$(selector);
+    const value = await document.$<T>(selector);
     return value;
   }
 
   async _document(): Promise<ElementHandle> {
     if (this._documentPromise) return this._documentPromise;
     this._documentPromise = this.executionContext().then(async (context) => {
       const document = await context.evaluateHandle('document');
       return document.asElement();
@@ -211,19 +213,21 @@ export class DOMWorld {
     const value = await document.$$eval<ReturnType>(
       selector,
       pageFunction,
       ...args
     );
     return value;
   }
 
-  async $$(selector: string): Promise<ElementHandle[]> {
+  async $$<T extends Element = Element>(
+    selector: string
+  ): Promise<Array<ElementHandle<T>>> {
     const document = await this._document();
-    const value = await document.$$(selector);
+    const value = await document.$$<T>(selector);
     return value;
   }
 
   async content(): Promise<string> {
     return await this.evaluate(() => {
       let retVal = '';
       if (document.doctype)
         retVal = new XMLSerializer().serializeToString(document.doctype);
--- a/remote/test/puppeteer/src/common/DeviceDescriptors.ts
+++ b/remote/test/puppeteer/src/common/DeviceDescriptors.ts
@@ -9,17 +9,20 @@
  *
  * 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.
  */
 
-interface Device {
+/**
+ * @public
+ */
+export interface Device {
   name: string;
   userAgent: string;
   viewport: {
     width: number;
     height: number;
     deviceScaleFactor: number;
     isMobile: boolean;
     hasTouch: boolean;
@@ -1025,18 +1028,21 @@ const devices: Device[] = [
       height: 411,
       deviceScaleFactor: 3.5,
       isMobile: true,
       hasTouch: true,
       isLandscape: true,
     },
   },
 ];
-
+/**
+ * @public
+ */
 export type DevicesMap = {
   [name: string]: Device;
 };
 
-const devicesMap: DevicesMap = {};
+/**
+ * @internal
+ */
+export const devicesMap: DevicesMap = {};
 
 for (const device of devices) devicesMap[device.name] = device;
-
-export { devicesMap };
--- a/remote/test/puppeteer/src/common/Dialog.ts
+++ b/remote/test/puppeteer/src/common/Dialog.ts
@@ -33,16 +33,17 @@ import { Protocol } from 'devtools-proto
  *   page.on('dialog', async dialog => {
  *     console.log(dialog.message());
  *     await dialog.dismiss();
  *     await browser.close();
  *   });
  *   page.evaluate(() => alert('1'));
  * })();
  * ```
+ * @public
  */
 export class Dialog {
   private _client: CDPSession;
   private _type: Protocol.Page.DialogType;
   private _message: string;
   private _defaultValue: string;
   private _handled = false;
 
--- a/remote/test/puppeteer/src/common/Errors.ts
+++ b/remote/test/puppeteer/src/common/Errors.ts
@@ -9,17 +9,20 @@
  *
  * 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.
  */
 
-class CustomError extends Error {
+/**
+ * @public
+ */
+export class CustomError extends Error {
   constructor(message: string) {
     super(message);
     this.name = this.constructor.name;
     Error.captureStackTrace(this, this.constructor);
   }
 }
 
 /**
@@ -28,14 +31,18 @@ class CustomError extends Error {
  * @remarks
  *
  * Example operations are {@link Page.waitForSelector | page.waitForSelector}
  * or {@link PuppeteerNode.launch | puppeteer.launch}.
  *
  * @public
  */
 export class TimeoutError extends CustomError {}
-
+/**
+ * @public
+ */
 export type PuppeteerErrors = Record<string, typeof CustomError>;
-
+/**
+ * @public
+ */
 export const puppeteerErrors: PuppeteerErrors = {
   TimeoutError,
 };
--- a/remote/test/puppeteer/src/common/EvalTypes.ts
+++ b/remote/test/puppeteer/src/common/EvalTypes.ts
@@ -15,17 +15,19 @@
  */
 
 import { JSHandle, ElementHandle } from './JSHandle.js';
 
 /**
  * @public
  */
 export type EvaluateFn<T = any> = string | ((arg1: T, ...args: any[]) => any);
-
+/**
+ * @public
+ */
 export type UnwrapPromiseLike<T> = T extends PromiseLike<infer U> ? U : T;
 
 /**
  * @public
  */
 export type EvaluateFnReturnType<T extends EvaluateFn> = T extends (
   ...args: any[]
 ) => infer R
--- a/remote/test/puppeteer/src/common/EventEmitter.ts
+++ b/remote/test/puppeteer/src/common/EventEmitter.ts
@@ -1,16 +1,21 @@
 import mitt, {
   Emitter,
   EventType,
   Handler,
 } from '../../vendor/mitt/src/index.js';
 
 /**
- * @internal
+ * @public
+ */
+export { EventType, Handler };
+
+/**
+ * @public
  */
 export interface CommonEventEmitter {
   on(event: EventType, handler: Handler): CommonEventEmitter;
   off(event: EventType, handler: Handler): CommonEventEmitter;
   /* To maintain parity with the built in NodeJS event emitter which uses removeListener
    * rather than `off`.
    * If you're implementing new code you should use `off`.
    */
--- a/remote/test/puppeteer/src/common/ExecutionContext.ts
+++ b/remote/test/puppeteer/src/common/ExecutionContext.ts
@@ -17,28 +17,30 @@
 import { assert } from './assert.js';
 import { helper } from './helper.js';
 import { createJSHandle, JSHandle, ElementHandle } from './JSHandle.js';
 import { CDPSession } from './Connection.js';
 import { DOMWorld } from './DOMWorld.js';
 import { Frame } from './FrameManager.js';
 import { Protocol } from 'devtools-protocol';
 import { EvaluateHandleFn, SerializableOrJSHandle } from './EvalTypes.js';
-
+/**
+ * @public
+ */
 export const EVALUATION_SCRIPT_URL = '__puppeteer_evaluation_script__';
 const SOURCE_URL_REGEX = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m;
 
 /**
  * This class represents a context for JavaScript execution. A [Page] might have
  * many execution contexts:
  * - each
  *   {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe |
  *   frame } has "default" execution context that is always created after frame is
  *   attached to DOM. This context is returned by the
- *   {@link frame.executionContext()} method.
+ *   {@link Frame.executionContext} method.
  * - {@link https://developer.chrome.com/extensions | Extension}'s content scripts
  *   create additional execution contexts.
  *
  * Besides pages, execution contexts can be found in
  * {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API |
  * workers }.
  *
  * @public
@@ -121,18 +123,18 @@ export class ExecutionContext {
    * const twoHandle = await executionContext.evaluateHandle(() => 2);
    * const result = await executionContext.evaluate(
    *    (a, b) => a + b, oneHandle, * twoHandle
    * );
    * await oneHandle.dispose();
    * await twoHandle.dispose();
    * console.log(result); // prints '3'.
    * ```
-   * @param pageFunction a function to be evaluated in the `executionContext`
-   * @param args argument to pass to the page function
+   * @param pageFunction - a function to be evaluated in the `executionContext`
+   * @param args - argument to pass to the page function
    *
    * @returns A promise that resolves to the return value of the given function.
    */
   async evaluate<ReturnType extends any>(
     pageFunction: Function | string,
     ...args: unknown[]
   ): Promise<ReturnType> {
     return await this._evaluateInternal<ReturnType>(
@@ -173,18 +175,18 @@ export class ExecutionContext {
    * ```js
    * const aHandle = await context.evaluateHandle(() => document.body);
    * const resultHandle = await context.evaluateHandle(body => body.innerHTML, * aHandle);
    * console.log(await resultHandle.jsonValue()); // prints body's innerHTML
    * await aHandle.dispose();
    * await resultHandle.dispose();
    * ```
    *
-   * @param pageFunction a function to be evaluated in the `executionContext`
-   * @param args argument to pass to the page function
+   * @param pageFunction - a function to be evaluated in the `executionContext`
+   * @param args - argument to pass to the page function
    *
    * @returns A promise that resolves to the return value of the given function
    * as an in-page object (a {@link JSHandle}).
    */
   async evaluateHandle<HandleType extends JSHandle | ElementHandle = JSHandle>(
     pageFunction: EvaluateHandleFn,
     ...args: SerializableOrJSHandle[]
   ): Promise<HandleType> {
@@ -339,17 +341,17 @@ export class ExecutionContext {
    * // Query all map instances into an array
    * const mapInstances = await page.queryObjects(mapPrototype);
    * // Count amount of map objects in heap
    * const count = await page.evaluate(maps => maps.length, mapInstances);
    * await mapInstances.dispose();
    * await mapPrototype.dispose();
    * ```
    *
-   * @param prototypeHandle a handle to the object prototype
+   * @param prototypeHandle - a handle to the object prototype
    *
    * @returns A handle to an array of objects with the given prototype.
    */
   async queryObjects(prototypeHandle: JSHandle): Promise<JSHandle> {
     assert(!prototypeHandle._disposed, 'Prototype JSHandle is disposed!');
     assert(
       prototypeHandle._remoteObject.objectId,
       'Prototype JSHandle must not be referencing primitive value'
--- a/remote/test/puppeteer/src/common/FileChooser.ts
+++ b/remote/test/puppeteer/src/common/FileChooser.ts
@@ -29,16 +29,17 @@ import { assert } from './assert.js';
  *   page.waitForFileChooser(),
  *   page.click('#upload-file-button'), // some button that triggers file selection
  * ]);
  * await fileChooser.accept(['/tmp/myfile.pdf']);
  * ```
  * **NOTE** In browsers, only one file chooser can be opened at a time.
  * All file choosers must be accepted or canceled. Not doing so will prevent
  * subsequent file choosers from appearing.
+ * @public
  */
 export class FileChooser {
   private _element: ElementHandle;
   private _multiple: boolean;
   private _handled = false;
 
   /**
    * @internal
@@ -70,16 +71,16 @@ export class FileChooser {
     );
     this._handled = true;
     await this._element.uploadFile(...filePaths);
   }
 
   /**
    * Closes the file chooser without selecting any files.
    */
-  async cancel(): Promise<void> {
+  cancel() {
     assert(
       !this._handled,
       'Cannot cancel FileChooser which is already handled!'
     );
     this._handled = true;
   }
 }
--- a/remote/test/puppeteer/src/common/FrameManager.ts
+++ b/remote/test/puppeteer/src/common/FrameManager.ts
@@ -717,18 +717,20 @@ export class Frame {
 
   /**
    * This method queries the frame for the given selector.
    *
    * @param selector - a selector to query for.
    * @returns A promise which resolves to an `ElementHandle` pointing at the
    * element, or `null` if it was not found.
    */
-  async $(selector: string): Promise<ElementHandle | null> {
-    return this._mainWorld.$(selector);
+  async $<T extends Element = Element>(
+    selector: string
+  ): Promise<ElementHandle<T> | null> {
+    return this._mainWorld.$<T>(selector);
   }
 
   /**
    * This method evaluates the given XPath expression and returns the results.
    *
    * @param expression - the XPath expression to evaluate.
    */
   async $x(expression: string): Promise<ElementHandle[]> {
@@ -796,18 +798,20 @@ export class Frame {
   }
 
   /**
    * This runs `document.querySelectorAll` in the frame and returns the result.
    *
    * @param selector - a selector to search for
    * @returns An array of element handles pointing to the found frame elements.
    */
-  async $$(selector: string): Promise<ElementHandle[]> {
-    return this._mainWorld.$$(selector);
+  async $$<T extends Element = Element>(
+    selector: string
+  ): Promise<Array<ElementHandle<T>>> {
+    return this._mainWorld.$$<T>(selector);
   }
 
   /**
    * @returns the full HTML contents of the frame, including the doctype.
    */
   async content(): Promise<string> {
     return this._secondaryWorld.content();
   }
--- a/remote/test/puppeteer/src/common/HTTPRequest.ts
+++ b/remote/test/puppeteer/src/common/HTTPRequest.ts
@@ -35,17 +35,20 @@ export interface ContinueRequestOverride
 
 /**
  * Required response data to fulfill a request with.
  *
  * @public
  */
 export interface ResponseForRequest {
   status: number;
-  headers: Record<string, string>;
+  /**
+   * Optional response headers. All values are converted to strings.
+   */
+  headers: Record<string, unknown>;
   contentType: string;
   body: string | Buffer;
 }
 
 /**
  * Resource types for HTTPRequests as perceived by the rendering engine.
  *
  * @public
@@ -341,32 +344,34 @@ export class HTTPRequest {
    * });
    * ```
    *
    * NOTE: Mocking responses for dataURL requests is not supported.
    * Calling `request.respond` for a dataURL request is a noop.
    *
    * @param response - the response to fulfill the request with.
    */
-  async respond(response: ResponseForRequest): Promise<void> {
+  async respond(response: Partial<ResponseForRequest>): Promise<void> {
     // Mocking responses for dataURL requests is not currently supported.
     if (this._url.startsWith('data:')) return;
     assert(this._allowInterception, 'Request Interception is not enabled!');
     assert(!this._interceptionHandled, 'Request is already handled!');
     this._interceptionHandled = true;
 
     const responseBody: Buffer | null =
       response.body && helper.isString(response.body)
         ? Buffer.from(response.body)
         : (response.body as Buffer) || null;
 
     const responseHeaders: Record<string, string> = {};
     if (response.headers) {
       for (const header of Object.keys(response.headers))
-        responseHeaders[header.toLowerCase()] = response.headers[header];
+        responseHeaders[header.toLowerCase()] = String(
+          response.headers[header]
+        );
     }
     if (response.contentType)
       responseHeaders['content-type'] = response.contentType;
     if (responseBody && !('content-length' in responseHeaders))
       responseHeaders['content-length'] = String(
         Buffer.byteLength(responseBody)
       );
 
--- a/remote/test/puppeteer/src/common/Input.ts
+++ b/remote/test/puppeteer/src/common/Input.ts
@@ -404,25 +404,24 @@ export class Mouse {
    */
   async click(
     x: number,
     y: number,
     options: MouseOptions & { delay?: number } = {}
   ): Promise<void> {
     const { delay = null } = options;
     if (delay !== null) {
-      await Promise.all([this.move(x, y), this.down(options)]);
+      await this.move(x, y);
+      await this.down(options);
       await new Promise((f) => setTimeout(f, delay));
       await this.up(options);
     } else {
-      await Promise.all([
-        this.move(x, y),
-        this.down(options),
-        this.up(options),
-      ]);
+      await this.move(x, y);
+      await this.down(options);
+      await this.up(options);
     }
   }
 
   /**
    * Dispatches a `mousedown` event.
    * @param options - Optional `MouseOptions`.
    */
   async down(options: MouseOptions = {}): Promise<void> {
--- a/remote/test/puppeteer/src/common/JSHandle.ts
+++ b/remote/test/puppeteer/src/common/JSHandle.ts
@@ -27,17 +27,19 @@ import {
   EvaluateFn,
   SerializableOrJSHandle,
   EvaluateFnReturnType,
   EvaluateHandleFn,
   WrapElementHandle,
   UnwrapPromiseLike,
 } from './EvalTypes.js';
 import { isNode } from '../environment.js';
-
+/**
+ * @public
+ */
 export interface BoxModel {
   content: Array<{ x: number; y: number }>;
   padding: Array<{ x: number; y: number }>;
   border: Array<{ x: number; y: number }>;
   margin: Array<{ x: number; y: number }>;
   width: number;
   height: number;
 }
@@ -766,28 +768,32 @@ export class ElementHandle<
 
     return imageData;
   }
 
   /**
    * Runs `element.querySelector` within the page. If no element matches the selector,
    * the return value resolves to `null`.
    */
-  async $(selector: string): Promise<ElementHandle | null> {
+  async $<T extends Element = Element>(
+    selector: string
+  ): Promise<ElementHandle<T> | null> {
     const { updatedSelector, queryHandler } = getQueryHandlerAndSelector(
       selector
     );
     return queryHandler.queryOne(this, updatedSelector);
   }
 
   /**
    * Runs `element.querySelectorAll` within the page. If no elements match the selector,
    * the return value resolves to `[]`.
    */
-  async $$(selector: string): Promise<ElementHandle[]> {
+  async $$<T extends Element = Element>(
+    selector: string
+  ): Promise<Array<ElementHandle<T>>> {
     const { updatedSelector, queryHandler } = getQueryHandlerAndSelector(
       selector
     );
     return queryHandler.queryAll(this, updatedSelector);
   }
 
   /**
    * This method runs `document.querySelector` within the element and passes it as
--- a/remote/test/puppeteer/src/common/LifecycleWatcher.ts
+++ b/remote/test/puppeteer/src/common/LifecycleWatcher.ts
@@ -21,23 +21,29 @@ import {
   FrameManager,
   Frame,
   FrameManagerEmittedEvents,
 } from './FrameManager.js';
 import { HTTPRequest } from './HTTPRequest.js';
 import { HTTPResponse } from './HTTPResponse.js';
 import { NetworkManagerEmittedEvents } from './NetworkManager.js';
 import { CDPSessionEmittedEvents } from './Connection.js';
-
+/**
+ * @public
+ */
 export type PuppeteerLifeCycleEvent =
   | 'load'
   | 'domcontentloaded'
   | 'networkidle0'
   | 'networkidle2';
-type ProtocolLifeCycleEvent =
+
+/**
+ * @public
+ */
+export type ProtocolLifeCycleEvent =
   | 'load'
   | 'DOMContentLoaded'
   | 'networkIdle'
   | 'networkAlmostIdle';
 
 const puppeteerToProtocolLifecycle = new Map<
   PuppeteerLifeCycleEvent,
   ProtocolLifeCycleEvent
--- a/remote/test/puppeteer/src/common/NetworkManager.ts
+++ b/remote/test/puppeteer/src/common/NetworkManager.ts
@@ -36,29 +36,32 @@ export interface Credentials {
 export interface NetworkConditions {
   // Download speed (bytes/s)
   download: number;
   // Upload speed (bytes/s)
   upload: number;
   // Latency (ms)
   latency: number;
 }
-
+/**
+ * @public
+ */
 export interface InternalNetworkConditions extends NetworkConditions {
   offline: boolean;
 }
 
 /**
  * We use symbols to prevent any external parties listening to these events.
  * They are internal to Puppeteer.
  *
  * @internal
  */
 export const NetworkManagerEmittedEvents = {
   Request: Symbol('NetworkManager.Request'),
+  RequestServedFromCache: Symbol('NetworkManager.RequestServedFromCache'),
   Response: Symbol('NetworkManager.Response'),
   RequestFailed: Symbol('NetworkManager.RequestFailed'),
   RequestFinished: Symbol('NetworkManager.RequestFinished'),
 } as const;
 
 /**
  * @internal
  */
@@ -70,16 +73,17 @@ export class NetworkManager extends Even
   _requestIdToRequestWillBeSentEvent = new Map<
     string,
     Protocol.Network.RequestWillBeSentEvent
   >();
   _extraHTTPHeaders: Record<string, string> = {};
   _credentials?: Credentials = null;
   _attemptedAuthentications = new Set<string>();
   _userRequestInterceptionEnabled = false;
+  _userRequestInterceptionCacheSafe = false;
   _protocolRequestInterceptionEnabled = false;
   _userCacheDisabled = false;
   _requestIdToInterceptionId = new Map<string, string>();
   _emulatedNetworkConditions: InternalNetworkConditions = {
     offline: false,
     upload: -1,
     download: -1,
     latency: 0,
@@ -184,18 +188,22 @@ export class NetworkManager extends Even
     await this._client.send('Network.setUserAgentOverride', { userAgent });
   }
 
   async setCacheEnabled(enabled: boolean): Promise<void> {
     this._userCacheDisabled = !enabled;
     await this._updateProtocolCacheDisabled();
   }
 
-  async setRequestInterception(value: boolean): Promise<void> {
+  async setRequestInterception(
+    value: boolean,
+    cacheSafe = false
+  ): Promise<void> {
     this._userRequestInterceptionEnabled = value;
+    this._userRequestInterceptionCacheSafe = cacheSafe;
     await this._updateProtocolRequestInterception();
   }
 
   async _updateProtocolRequestInterception(): Promise<void> {
     const enabled = this._userRequestInterceptionEnabled || !!this._credentials;
     if (enabled === this._protocolRequestInterceptionEnabled) return;
     this._protocolRequestInterceptionEnabled = enabled;
     if (enabled) {
@@ -212,24 +220,26 @@ export class NetworkManager extends Even
         this._client.send('Fetch.disable'),
       ]);
     }
   }
 
   async _updateProtocolCacheDisabled(): Promise<void> {
     await this._client.send('Network.setCacheDisabled', {
       cacheDisabled:
-        this._userCacheDisabled || this._protocolRequestInterceptionEnabled,
+        this._userCacheDisabled ||
+        (this._userRequestInterceptionEnabled &&
+          !this._userRequestInterceptionCacheSafe),
     });
   }
 
   _onRequestWillBeSent(event: Protocol.Network.RequestWillBeSentEvent): void {
     // Request interception doesn't happen for data URLs with Network Service.
     if (
-      this._protocolRequestInterceptionEnabled &&
+      this._userRequestInterceptionEnabled &&
       !event.request.url.startsWith('data:')
     ) {
       const requestId = event.requestId;
       const interceptionId = this._requestIdToInterceptionId.get(requestId);
       if (interceptionId) {
         this._onRequest(event, interceptionId);
         this._requestIdToInterceptionId.delete(requestId);
       } else {
@@ -318,16 +328,17 @@ export class NetworkManager extends Even
     this.emit(NetworkManagerEmittedEvents.Request, request);
   }
 
   _onRequestServedFromCache(
     event: Protocol.Network.RequestServedFromCacheEvent
   ): void {
     const request = this._requestIdToRequest.get(event.requestId);
     if (request) request._fromMemoryCache = true;
+    this.emit(NetworkManagerEmittedEvents.RequestServedFromCache, request);
   }
 
   _handleRequestRedirect(
     request: HTTPRequest,
     responsePayload: Protocol.Network.Response
   ): void {
     const response = new HTTPResponse(this._client, request, responsePayload);
     request._response = response;
--- a/remote/test/puppeteer/src/common/PDFOptions.ts
+++ b/remote/test/puppeteer/src/common/PDFOptions.ts
@@ -146,16 +146,21 @@ export interface PDFOptions {
    *
    * @remarks
    *
    * If the path is relative, it's resolved relative to the current working directory.
    *
    * @defaultValue the empty string, which means the PDF will not be written to disk.
    */
   path?: string;
+  /**
+   * Hides default white background and allows generating pdfs with transparency.
+   * @defaultValue false
+   */
+  omitBackground?: boolean;
 }
 
 /**
  * @internal
  */
 export interface PaperFormatDimensions {
   width: number;
   height: number;
--- a/remote/test/puppeteer/src/common/Page.ts
+++ b/remote/test/puppeteer/src/common/Page.ts
@@ -125,17 +125,20 @@ export interface GeolocationOptions {
    */
   latitude: number;
   /**
    * Optional non-negative accuracy value.
    */
   accuracy?: number;
 }
 
-interface MediaFeature {
+/**
+ * @public
+ */
+export interface MediaFeature {
   name: string;
   value: string;
 }
 
 /**
  * @public
  */
 export interface ScreenshotClip {
@@ -178,16 +181,21 @@ export interface ScreenshotOptions {
    * @defaultValue false
    */
   omitBackground?: boolean;
   /**
    * Encoding of the image.
    * @defaultValue 'binary'
    */
   encoding?: 'base64' | 'binary';
+  /**
+   * If you need a screenshot bigger than the Viewport
+   * @defaultValue true
+   */
+  captureBeyondViewport?: boolean;
 }
 
 /**
  * All the events that a page instance may emit.
  *
  * @public
  */
 export const enum PageEmittedEvents {
@@ -278,21 +286,29 @@ export const enum PageEmittedEvents {
    * ]);
    * ```
    */
   Popup = 'popup',
   /**
    * Emitted when a page issues a request and contains a {@link HTTPRequest}.
    *
    * @remarks
-   * The object is readonly. See {@Page.setRequestInterception} for intercepting
+   * The object is readonly. See {@link Page.setRequestInterception} for intercepting
    * and mutating requests.
    */
   Request = 'request',
   /**
+   * Emitted when a request ended up loading from cache. Contains a {@link HTTPRequest}.
+   *
+   * @remarks
+   * For certain requests, might contain undefined.
+   * {@link https://crbug.com/750469}
+   */
+  RequestServedFromCache = 'requestservedfromcache',
+  /**
    * Emitted when a request fails, for example by timing out.
    *
    * Contains a {@link HTTPRequest}.
    *
    * @remarks
    *
    * NOTE: HTTP Error responses, such as 404 or 503, are still successful
    * responses from HTTP standpoint, so request will complete with
@@ -316,16 +332,45 @@ export const enum PageEmittedEvents {
   /**
    * Emitted when a dedicated
    * {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API | WebWorker}
    * is destroyed by the page.
    */
   WorkerDestroyed = 'workerdestroyed',
 }
 
+/**
+ * Denotes the objects received by callback functions for page events.
+ *
+ * See {@link PageEmittedEvents} for more detail on the events and when they are
+ * emitted.
+ * @public
+ */
+export interface PageEventObject {
+  close: never;
+  console: ConsoleMessage;
+  dialog: Dialog;
+  domcontentloaded: never;
+  error: Error;
+  frameattached: Frame;
+  framedetached: Frame;
+  framenavigated: Frame;
+  load: never;
+  metrics: { title: string; metrics: Metrics };
+  pageerror: Error;
+  popup: Page;
+  request: HTTPRequest;
+  response: HTTPResponse;
+  requestfailed: HTTPRequest;
+  requestfinished: HTTPRequest;
+  requestservedfromcache: HTTPRequest;
+  workercreated: WebWorker;
+  workerdestroyed: WebWorker;
+}
+
 class ScreenshotTaskQueue {
   _chain: Promise<Buffer | string | void>;
 
   constructor() {
     this._chain = Promise.resolve<Buffer | string | void>(undefined);
   }
 
   public postTask(
@@ -460,34 +505,38 @@ export class Page extends EventEmitter {
         this._handleException.bind(this)
       );
       this._workers.set(event.sessionId, worker);
       this.emit(PageEmittedEvents.WorkerCreated, worker);
     });
     client.on('Target.detachedFromTarget', (event) => {
       const worker = this._workers.get(event.sessionId);
       if (!worker) return;
+      this._workers.delete(event.sessionId);
       this.emit(PageEmittedEvents.WorkerDestroyed, worker);
-      this._workers.delete(event.sessionId);
     });
 
     this._frameManager.on(FrameManagerEmittedEvents.FrameAttached, (event) =>
       this.emit(PageEmittedEvents.FrameAttached, event)
     );
     this._frameManager.on(FrameManagerEmittedEvents.FrameDetached, (event) =>
       this.emit(PageEmittedEvents.FrameDetached, event)
     );
     this._frameManager.on(FrameManagerEmittedEvents.FrameNavigated, (event) =>
       this.emit(PageEmittedEvents.FrameNavigated, event)
     );
 
     const networkManager = this._frameManager.networkManager();
     networkManager.on(NetworkManagerEmittedEvents.Request, (event) =>
       this.emit(PageEmittedEvents.Request, event)
     );
+    networkManager.on(
+      NetworkManagerEmittedEvents.RequestServedFromCache,
+      (event) => this.emit(PageEmittedEvents.RequestServedFromCache, event)
+    );
     networkManager.on(NetworkManagerEmittedEvents.Response, (event) =>
       this.emit(PageEmittedEvents.Response, event)
     );
     networkManager.on(NetworkManagerEmittedEvents.RequestFailed, (event) =>
       this.emit(PageEmittedEvents.RequestFailed, event)
     );
     networkManager.on(NetworkManagerEmittedEvents.RequestFinished, (event) =>
       this.emit(PageEmittedEvents.RequestFinished, event)
@@ -543,16 +592,37 @@ export class Page extends EventEmitter {
   /**
    * @returns `true` if the page has JavaScript enabled, `false` otherwise.
    */
   public isJavaScriptEnabled(): boolean {
     return this._javascriptEnabled;
   }
 
   /**
+   * Listen to page events.
+   */
+  public on<K extends keyof PageEventObject>(
+    eventName: K,
+    handler: (event: PageEventObject[K]) => void
+  ): EventEmitter {
+    // Note: this method only exists to define the types; we delegate the impl
+    // to EventEmitter.
+    return super.on(eventName, handler);
+  }
+
+  public once<K extends keyof PageEventObject>(
+    eventName: K,
+    handler: (event: PageEventObject[K]) => void
+  ): EventEmitter {
+    // Note: this method only exists to define the types; we delegate the impl
+    // to EventEmitter.
+    return super.once(eventName, handler);
+  }
+
+  /**
    * @param options - Optional waiting parameters
    * @returns Resolves after a page requests a file picker.
    */
   async waitForFileChooser(
     options: WaitTimeoutOptions = {}
   ): Promise<FileChooser> {
     if (!this._fileChooserInterceptors.size)
       await this._client.send('Page.setInterceptFileChooserDialog', {
@@ -683,26 +753,26 @@ export class Page extends EventEmitter {
    * associated with the page.
    */
   workers(): WebWorker[] {
     return Array.from(this._workers.values());
   }
 
   /**
    * @param value - Whether to enable request interception.
+   * @param cacheSafe - Whether to trust browser caching. If set to false,
+   * enabling request interception disables page caching. Defaults to false.
    *
    * @remarks
    * Activating request interception enables {@link HTTPRequest.abort},
    * {@link HTTPRequest.continue} and {@link HTTPRequest.respond} methods.  This
    * provides the capability to modify network requests that are made by a page.
    *
    * Once request interception is enabled, every request will stall unless it's
-   * continued, responded or aborted.
-   *
-   * **NOTE** Enabling request interception disables page caching.
+   * continued, responded or aborted; or completed using the browser cache.
    *
    * @example
    * An example of a naïve request interceptor that aborts all image requests:
    * ```js
    * const puppeteer = require('puppeteer');
    * (async () => {
    *   const browser = await puppeteer.launch();
    *   const page = await browser.newPage();
@@ -714,18 +784,23 @@ export class Page extends EventEmitter {
    *     else
    *       interceptedRequest.continue();
    *     });
    *   await page.goto('https://example.com');
    *   await browser.close();
    * })();
    * ```
    */
-  async setRequestInterception(value: boolean): Promise<void> {
-    return this._frameManager.networkManager().setRequestInterception(value);
+  async setRequestInterception(
+    value: boolean,
+    cacheSafe = false
+  ): Promise<void> {
+    return this._frameManager
+      .networkManager()
+      .setRequestInterception(value, cacheSafe);
   }
 
   /**
    * @param enabled - When `true`, enables offline mode for the page.
    */
   setOfflineMode(enabled: boolean): Promise<void> {
     return this._frameManager.networkManager().setOfflineMode(enabled);
   }
@@ -758,18 +833,20 @@ export class Page extends EventEmitter {
    *
    * @remarks
    * Shortcut for {@link Frame.$ | Page.mainFrame().$(selector) }.
    *
    * @param selector - A
    * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | selector}
    * to query page for.
    */
-  async $(selector: string): Promise<ElementHandle | null> {
-    return this.mainFrame().$(selector);
+  async $<T extends Element = Element>(
+    selector: string
+  ): Promise<ElementHandle<T> | null> {
+    return this.mainFrame().$<T>(selector);
   }
 
   /**
    * @remarks
    *
    * The only difference between {@link Page.evaluate | page.evaluate} and
    * `page.evaluateHandle` is that `evaluateHandle` will return the value
    * wrapped in an in-page object.
@@ -975,23 +1052,23 @@ export class Page extends EventEmitter {
    * ```
    * // The compiler can infer the return type in this case, but if it can't
    * // or if you want to be more explicit, provide it as the generic type.
    * const allInputValues = await page.$$eval<string[]>(
    *  'input', (elements: HTMLInputElement[]) => elements.map(e => e.textContent)
    * );
    * ```
    *
-   * @param selector the
+   * @param selector - the
    * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | selector}
    * to query for
-   * @param pageFunction the function to be evaluated in the page context. Will
+   * @param pageFunction - the function to be evaluated in the page context. Will
    * be passed the result of `Array.from(document.querySelectorAll(selector))`
    * as its first argument.
-   * @param args any additional arguments to pass through to `pageFunction`.
+   * @param args - any additional arguments to pass through to `pageFunction`.
    *
    * @returns The result of calling `pageFunction`. If it returns an element it
    * is wrapped in an {@link ElementHandle}, else the raw value itself is
    * returned.
    */
   async $$eval<ReturnType>(
     selector: string,
     pageFunction: (
@@ -1002,18 +1079,20 @@ export class Page extends EventEmitter {
        */
       ...args: unknown[]
     ) => ReturnType | Promise<ReturnType>,
     ...args: SerializableOrJSHandle[]
   ): Promise<WrapElementHandle<ReturnType>> {
     return this.mainFrame().$$eval<ReturnType>(selector, pageFunction, ...args);
   }
 
-  async $$(selector: string): Promise<ElementHandle[]> {
-    return this.mainFrame().$$(selector);
+  async $$<T extends Element = Element>(
+    selector: string
+  ): Promise<Array<ElementHandle<T>>> {
+    return this.mainFrame().$$<T>(selector);
   }
 
   async $x(expression: string): Promise<ElementHandle[]> {
     return this.mainFrame().$x(expression);
   }
 
   /**
    * If no URLs are specified, this method returns cookies for the current page
@@ -1266,16 +1345,32 @@ export class Page extends EventEmitter {
       this._client,
       dialogType,
       event.message,
       event.defaultPrompt
     );
     this.emit(PageEmittedEvents.Dialog, dialog);
   }
 
+  /**
+   * Resets default white background
+   */
+  private async _resetDefaultBackgroundColor() {
+    await this._client.send('Emulation.setDefaultBackgroundColorOverride');
+  }
+
+  /**
+   * Hides default white background
+   */
+  private async _setTransparentBackgroundColor(): Promise<void> {
+    await this._client.send('Emulation.setDefaultBackgroundColorOverride', {
+      color: { r: 0, g: 0, b: 0, a: 0 },
+    });
+  }
+
   url(): string {
     return this.mainFrame().url();
   }
 
   async content(): Promise<string> {
     return await this._frameManager.mainFrame().content();
   }
 
@@ -1311,17 +1406,17 @@ export class Page extends EventEmitter {
         this._client.once(CDPSessionEmittedEvents.Disconnected, () =>
           fulfill(new Error('Target closed'))
         )
       );
     return this._disconnectPromise;
   }
 
   async waitForRequest(
-    urlOrPredicate: string | Function,
+    urlOrPredicate: string | ((req: HTTPRequest) => boolean | Promise<boolean>),
     options: { timeout?: number } = {}
   ): Promise<HTTPRequest> {
     const { timeout = this._timeoutSettings.timeout() } = options;
     return helper.waitForEvent(
       this._frameManager.networkManager(),
       NetworkManagerEmittedEvents.Request,
       (request) => {
         if (helper.isString(urlOrPredicate))
@@ -1331,17 +1426,19 @@ export class Page extends EventEmitter {
         return false;
       },
       timeout,
       this._sessionClosePromise()
     );
   }
 
   async waitForResponse(
-    urlOrPredicate: string | Function,
+    urlOrPredicate:
+      | string
+      | ((res: HTTPResponse) => boolean | Promise<boolean>),
     options: { timeout?: number } = {}
   ): Promise<HTTPResponse> {
     const { timeout = this._timeoutSettings.timeout() } = options;
     return helper.waitForEvent(
       this._frameManager.networkManager(),
       NetworkManagerEmittedEvents.Response,
       async (response) => {
         if (helper.isString(urlOrPredicate))
@@ -1456,19 +1553,19 @@ export class Page extends EventEmitter {
    *
    * // do some checks here
    * ...
    *
    * // clear idle emulation
    * await page.emulateIdleState();
    * ```
    *
-   * @param overrides Mock idle state. If not set, clears idle overrides
-   * @param isUserActive Mock isUserActive
-   * @param isScreenUnlocked Mock isScreenUnlocked
+   * @param overrides - Mock idle state. If not set, clears idle overrides
+   * @param isUserActive - Mock isUserActive
+   * @param isScreenUnlocked - Mock isScreenUnlocked
    */
   async emulateIdleState(overrides?: {
     isUserActive: boolean;
     isScreenUnlocked: boolean;
   }): Promise<void> {
     if (overrides) {
       await this._client.send('Emulation.setIdleOverride', {
         isUserActive: overrides.isUserActive,
@@ -1704,54 +1801,76 @@ export class Page extends EventEmitter {
   private async _screenshotTask(
     format: 'png' | 'jpeg',
     options?: ScreenshotOptions
   ): Promise<Buffer | string> {
     await this._client.send('Target.activateTarget', {
       targetId: this._target._targetId,
     });
     let clip = options.clip ? processClip(options.clip) : undefined;
+    let { captureBeyondViewport = true } = options;
+    captureBeyondViewport =
+      typeof captureBeyondViewport === 'boolean' ? captureBeyondViewport : true;
 
     if (options.fullPage) {
       const metrics = await this._client.send('Page.getLayoutMetrics');
       const width = Math.ceil(metrics.contentSize.width);
       const height = Math.ceil(metrics.contentSize.height);
 
       // Overwrite clip for full page.
       clip = { x: 0, y: 0, width, height, scale: 1 };
+
+      if (!captureBeyondViewport) {
+        const { isMobile = false, deviceScaleFactor = 1, isLandscape = false } =
+          this._viewport || {};
+        const screenOrientation: Protocol.Emulation.ScreenOrientation = isLandscape
+          ? { angle: 90, type: 'landscapePrimary' }
+          : { angle: 0, type: 'portraitPrimary' };
+        await this._client.send('Emulation.setDeviceMetricsOverride', {
+          mobile: isMobile,
+          width,
+          height,
+          deviceScaleFactor,
+          screenOrientation,
+        });
+      }
     }
     const shouldSetDefaultBackground =
       options.omitBackground && format === 'png';
-    if (shouldSetDefaultBackground)
-      await this._client.send('Emulation.setDefaultBackgroundColorOverride', {
-        color: { r: 0, g: 0, b: 0, a: 0 },
-      });
+    if (shouldSetDefaultBackground) {
+      await this._setTransparentBackgroundColor();
+    }
+
     const result = await this._client.send('Page.captureScreenshot', {
       format,
       quality: options.quality,
       clip,
-      captureBeyondViewport: true,
+      captureBeyondViewport,
     });
-    if (shouldSetDefaultBackground)
-      await this._client.send('Emulation.setDefaultBackgroundColorOverride');
+    if (shouldSetDefaultBackground) {
+      await this._resetDefaultBackgroundColor();
+    }
 
     if (options.fullPage && this._viewport)
       await this.setViewport(this._viewport);
 
     const buffer =
       options.encoding === 'base64'
         ? result.data
         : Buffer.from(result.data, 'base64');
-    if (!isNode && options.path) {
-      throw new Error(
-        'Screenshots can only be written to a file path in a Node environment.'
-      );
+
+    if (options.path) {
+      if (!isNode) {
+        throw new Error(
+          'Screenshots can only be written to a file path in a Node environment.'
+        );
+      }
+      const fs = await helper.importFSModule();
+      await fs.promises.writeFile(options.path, buffer);
     }
-    const fs = await helper.importFSModule();
-    if (options.path) await fs.promises.writeFile(options.path, buffer);
     return buffer;
 
     function processClip(
       clip: ScreenshotClip
     ): ScreenshotClip & { scale: number } {
       const x = Math.round(clip.x);
       const y = Math.round(clip.y);
       const width = Math.round(clip.width + clip.x - x);
@@ -1785,16 +1904,17 @@ export class Page extends EventEmitter {
       headerTemplate = '',
       footerTemplate = '',
       printBackground = false,
       landscape = false,
       pageRanges = '',
       preferCSSPageSize = false,
       margin = {},
       path = null,
+      omitBackground = false,
     } = options;
 
     let paperWidth = 8.5;
     let paperHeight = 11;
     if (options.format) {
       const format = paperFormats[options.format.toLowerCase()];
       assert(format, 'Unknown paper format: ' + options.format);
       paperWidth = format.width;
@@ -1805,16 +1925,20 @@ export class Page extends EventEmitter {
         convertPrintParameterToInches(options.height) || paperHeight;
     }
 
     const marginTop = convertPrintParameterToInches(margin.top) || 0;
     const marginLeft = convertPrintParameterToInches(margin.left) || 0;
     const marginBottom = convertPrintParameterToInches(margin.bottom) || 0;
     const marginRight = convertPrintParameterToInches(margin.right) || 0;
 
+    if (omitBackground) {
+      await this._setTransparentBackgroundColor();
+    }
+
     const result = await this._client.send('Page.printToPDF', {
       transferMode: 'ReturnAsStream',
       landscape,
       displayHeaderFooter,
       headerTemplate,
       footerTemplate,
       printBackground,
       scale,
@@ -1822,16 +1946,21 @@ export class Page extends EventEmitter {
       paperHeight,
       marginTop,
       marginBottom,
       marginLeft,
       marginRight,
       pageRanges,
       preferCSSPageSize,
     });
+
+    if (omitBackground) {
+      await this._resetDefaultBackgroundColor();
+    }
+
     return await helper.readProtocolStream(this._client, result.stream, path);
   }
 
   async title(): Promise<string> {
     return this.mainFrame().title();
   }
 
   async close(
--- a/remote/test/puppeteer/src/common/Puppeteer.ts
+++ b/remote/test/puppeteer/src/common/Puppeteer.ts
@@ -33,17 +33,19 @@ import {
 
 /**
  * Settings that are common to the Puppeteer class, regardless of enviroment.
  * @internal
  */
 export interface CommonPuppeteerSettings {
   isPuppeteerCore: boolean;
 }
-
+/**
+ * @public
+ */
 export interface ConnectOptions extends BrowserConnectOptions {
   browserWSEndpoint?: string;
   browserURL?: string;
   transport?: ConnectionTransport;
   product?: Product;
 }
 
 /**
--- a/remote/test/puppeteer/src/common/WebWorker.ts
+++ b/remote/test/puppeteer/src/common/WebWorker.ts
@@ -19,26 +19,26 @@ import { ExecutionContext } from './Exec
 import { JSHandle } from './JSHandle.js';
 import { CDPSession } from './Connection.js';
 import { Protocol } from 'devtools-protocol';
 import { EvaluateHandleFn, SerializableOrJSHandle } from './EvalTypes.js';
 
 /**
  * @internal
  */
-type ConsoleAPICalledCallback = (
+export type ConsoleAPICalledCallback = (
   eventType: string,
   handles: JSHandle[],
   trace: Protocol.Runtime.StackTrace
 ) => void;
 
 /**
  * @internal
  */
-type ExceptionThrownCallback = (
+export type ExceptionThrownCallback = (
   details: Protocol.Runtime.ExceptionDetails
 ) => void;
 type JSHandleFactory = (obj: Protocol.Runtime.RemoteObject) => JSHandle;
 
 /**
  * The WebWorker class represents a
  * {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API | WebWorker}.
  *
--- a/remote/test/puppeteer/src/common/helper.ts
+++ b/remote/test/puppeteer/src/common/helper.ts
@@ -81,16 +81,19 @@ async function releaseObject(
     .send('Runtime.releaseObject', { objectId: remoteObject.objectId })
     .catch((error) => {
       // Exceptions might happen in case of a page been navigated or closed.
       // Swallow these since they are harmless and we don't leak anything in this case.
       debugError(error);
     });
 }
 
+/**
+ * @public
+ */
 export interface PuppeteerEventListener {
   emitter: CommonEventEmitter;
   eventName: string | symbol;
   handler: (...args: any[]) => void;
 }
 
 function addEventListener(
   emitter: CommonEventEmitter,
--- a/remote/test/puppeteer/src/node/BrowserFetcher.ts
+++ b/remote/test/puppeteer/src/node/BrowserFetcher.ts
@@ -288,17 +288,20 @@ export class BrowserFetcher {
       revision
     );
     const fileName = url.split('/').pop();
     const archivePath = path.join(this._downloadsFolder, fileName);
     const outputPath = this._getFolderPath(revision);
     if (await existsAsync(outputPath)) return this.revisionInfo(revision);
     if (!(await existsAsync(this._downloadsFolder)))
       await mkdirAsync(this._downloadsFolder);
-    if (os.arch() === 'arm64') {
+
+    // Use Intel x86 builds on Apple M1 until native macOS arm64
+    // Chromium builds are available.
+    if (os.platform() !== 'darwin' && os.arch() === 'arm64') {
       handleArm64();
       return;
     }
     try {
       await downloadFile(url, archivePath, progressCallback);
       await install(archivePath, outputPath);
     } finally {
       if (await existsAsync(archivePath)) await unlinkAsync(archivePath);
--- a/remote/test/puppeteer/src/node/Launcher.ts
+++ b/remote/test/puppeteer/src/node/Launcher.ts
@@ -100,17 +100,19 @@ class ChromeLauncher implements ProductL
       );
     if (!chromeArguments.some((arg) => arg.startsWith('--user-data-dir'))) {
       temporaryUserDataDir = await mkdtempAsync(profilePath);
       chromeArguments.push(`--user-data-dir=${temporaryUserDataDir}`);
     }
 
     let chromeExecutable = executablePath;
     if (!executablePath) {
-      if (os.arch() === 'arm64') {
+      // Use Intel x86 builds on Apple M1 until native macOS arm64
+      // Chromium builds are available.
+      if (os.platform() !== 'darwin' && os.arch() === 'arm64') {
         chromeExecutable = '/usr/bin/chromium-browser';
       } else {
         const { missingText, executablePath } = resolveExecutablePath(this);
         if (missingText) throw new Error(missingText);
         chromeExecutable = executablePath;
       }
     }
 
@@ -497,16 +499,18 @@ class FirefoxLauncher implements Product
       'general.useragent.updates.enabled': false,
       // Always use network provider for geolocation tests so we bypass the
       // macOS dialog raised by the corelocation provider
       'geo.provider.testing': true,
       // Do not scan Wifi
       'geo.wifi.scan': false,
       // No hang monitor
       'hangmonitor.timeout': 0,
+      // Show chrome errors and warnings in the error console
+      'javascript.options.showInConsole': true,
 
       // Disable download and usage of OpenH264: and Widevine plugins
       'media.gmp-manager.updateEnabled': false,
       // Prevent various error message on the console
       // jest-puppeteer asserts that no error message is emitted by the console
       'network.cookie.cookieBehavior': 0,
 
       // Disable experimental feature that is only available in Nightly
@@ -525,18 +529,18 @@ class FirefoxLauncher implements Product
       // Make sure SNTP requests do not hit the network
       'network.sntp.pools': server,
 
       // Disable Flash.
       'plugin.state.flash': 0,
 
       'privacy.trackingprotection.enabled': false,
 
-      // Can be removed once Firefox 89 is no longer supported
-      // https://bugzilla.mozilla.org/show_bug.cgi?id=1710839
+      // Enable Remote Agent
+      // https://bugzilla.mozilla.org/show_bug.cgi?id=1544393
       'remote.enabled': true,
 
       // Don't do network connections for mitm priming
       'security.certerrors.mitm.priming.enabled': false,
       // Local documents have access to all other local documents,
       // including directory listings
       'security.fileuri.strict_origin_policy': false,
       // Do not wait for the notification button security delay
--- a/remote/test/puppeteer/src/node/install.ts
+++ b/remote/test/puppeteer/src/node/install.ts
@@ -85,17 +85,19 @@ export async function downloadBrowser() 
       process.env.npm_config_http_proxy || process.env.npm_config_proxy;
     const NPM_NO_PROXY = process.env.npm_config_no_proxy;
 
     if (NPM_HTTPS_PROXY) process.env.HTTPS_PROXY = NPM_HTTPS_PROXY;
     if (NPM_HTTP_PROXY) process.env.HTTP_PROXY = NPM_HTTP_PROXY;
     if (NPM_NO_PROXY) process.env.NO_PROXY = NPM_NO_PROXY;
 
     function onSuccess(localRevisions: string[]): void {
-      if (os.arch() !== 'arm64') {
+      // Use Intel x86 builds on Apple M1 until native macOS arm64
+      // Chromium builds are available.
+      if (os.platform() !== 'darwin' && os.arch() !== 'arm64') {
         logPolitely(
           `${supportedProducts[product]} (${revisionInfo.revision}) downloaded to ${revisionInfo.folderPath}`
         );
       }
       localRevisions = localRevisions.filter(
         (revision) => revision !== revisionInfo.revision
       );
       const cleanupOldVersions = localRevisions.map((revision) =>
--- a/remote/test/puppeteer/src/revisions.ts
+++ b/remote/test/puppeteer/src/revisions.ts
@@ -15,11 +15,11 @@
  */
 
 type Revisions = Readonly<{
   readonly chromium: string;
   readonly firefox: string;
 }>;
 
 export const PUPPETEER_REVISIONS: Revisions = {
-  chromium: '856583',
+  chromium: '869685',
   firefox: 'latest',
 };
--- a/remote/test/puppeteer/test-ts-types/ts-cjs-import-cjs-output/good.ts
+++ b/remote/test/puppeteer/test-ts-types/ts-cjs-import-cjs-output/good.ts
@@ -1,13 +1,16 @@
 import puppeteer = require('puppeteer');
 
 async function run() {
   const browser = await puppeteer.launch();
   const devices = puppeteer.devices;
   console.log(devices);
   const page = await browser.newPage();
+  page.on('request', (request) => {
+    const resourceType = request.resourceType();
+  });
   const div = (await page.$('div')) as puppeteer.ElementHandle<
     HTMLAnchorElement
   >;
   console.log('got a div!', div);
 }
 run();
--- a/remote/test/puppeteer/test/README.md
+++ b/remote/test/puppeteer/test/README.md
@@ -1,74 +1,73 @@
 # Puppeteer unit tests
 
 Unit tests in Puppeteer are written using [Mocha] as the test runner and [Expect] as the assertions library.
 
 ## Test state
 
-
 We have some common setup that runs before each test and is defined in `mocha-utils.js`.
 
 You can use the `getTestState` function to read state. It exposes the following that you can use in your tests. These will be reset/tidied between tests automatically for you:
 
-* `puppeteer`: an instance of the Puppeteer library. This is exactly what you'd get if you ran `require('puppeteer')`.
-* `puppeteerPath`: the path to the root source file for Puppeteer.
-* `defaultBrowserOptions`: the default options the Puppeteer browser is launched from in test mode, so tests can use them and override if required.
-* `server`: a dummy test server instance (see `utils/testserver` for more).
-* `httpsServer`: a dummy test server HTTPS instance (see `utils/testserver` for more).
-* `isFirefox`: true if running in Firefox.
-* `isChrome`: true if running Chromium.
-* `isHeadless`: true if the test is in headless mode.
+- `puppeteer`: an instance of the Puppeteer library. This is exactly what you'd get if you ran `require('puppeteer')`.
+- `puppeteerPath`: the path to the root source file for Puppeteer.
+- `defaultBrowserOptions`: the default options the Puppeteer browser is launched from in test mode, so tests can use them and override if required.
+- `server`: a dummy test server instance (see `utils/testserver` for more).
+- `httpsServer`: a dummy test server HTTPS instance (see `utils/testserver` for more).
+- `isFirefox`: true if running in Firefox.
+- `isChrome`: true if running Chromium.
+- `isHeadless`: true if the test is in headless mode.
 
 If your test needs a browser instance, you can use the `setupTestBrowserHooks()` function which will automatically configure a browser that will be cleaned between each test suite run. You access this via `getTestState()`.
 
 If your test needs a Puppeteer page and context, you can use the `setupTestPageAndContextHooks()` function which will configure these. You can access `page` and `context` from `getTestState()` once you have done this.
 
 The best place to look is an existing test to see how they use the helpers.
 
 ## Skipping tests in specific conditions
 
 Tests that are not expected to pass in Firefox can be skipped. You can skip an individual test by using `itFailsFirefox` rather than `it`. Similarly you can skip a describe block with `describeFailsFirefox`.
 
 There is also `describeChromeOnly` and `itChromeOnly` which will only execute the test if running in Chromium. Note that this is different from `describeFailsFirefox`: the goal is to get any `FailsFirefox` calls passing in Firefox, whereas `describeChromeOnly` should be used to test behaviour that will only ever apply in Chromium.
 
 There are also tests that assume a normal install flow, with browser binaries ending up in `.local-<browser>`, for example. Such tests are skipped with
 `itOnlyRegularInstall` which checks `BINARY` and `PUPPETEER_ALT_INSTALL` environment variables.
 
-[Mocha]: https://mochajs.org/
-[Expect]: https://www.npmjs.com/package/expect
+[mocha]: https://mochajs.org/
+[expect]: https://www.npmjs.com/package/expect
 
 ## Running tests
 
 Despite being named 'unit', these are integration tests, making sure public API methods and events work as expected.
 
 - To run all tests:
 
 ```bash
 npm run unit
 ```
 
-- __Important__: don't forget to first run TypeScript if you're testing local changes:
+- **Important**: don't forget to first run TypeScript if you're testing local changes:
 
 ```bash
 npm run tsc && npm run unit
 ```
 
 - To run a specific test, substitute the `it` with `it.only`:
 
 ```js
   ...
   it.only('should work', async function() {
     const {server, page} = getTestState();
     const response = await page.goto(server.EMPTY_PAGE);
     expect(response.ok).toBe(true);
   });
 ```
 
-- To disable a specific test, substitute the `it` with `xit` (mnemonic rule: '*cross it*'):
+- To disable a specific test, substitute the `it` with `xit` (mnemonic rule: '_cross it_'):
 
 ```js
   ...
   // Using "xit" to skip specific test
   xit('should work', async function({server, page}) {
     const {server, page} = getTestState();
     const response = await page.goto(server.EMPTY_PAGE);
     expect(response.ok).toBe(true);
--- a/remote/test/puppeteer/test/accessibility.spec.ts
+++ b/remote/test/puppeteer/test/accessibility.spec.ts
@@ -429,17 +429,17 @@ describeFailsFirefox('Accessibility', fu
     });
 
     describe('root option', function () {
       it('should work a button', async () => {
         const { page } = getTestState();
 
         await page.setContent(`<button>My Button</button>`);
 
-        const button = await page.$('button');
+        const button = await page.$<HTMLButtonElement>('button');
         expect(await page.accessibility.snapshot({ root: button })).toEqual({
           role: 'button',
           name: 'My Button',
         });
       });
       it('should work an input', async () => {
         const { page } = getTestState();
 
--- a/remote/test/puppeteer/test/ariaqueryhandler.spec.ts
+++ b/remote/test/puppeteer/test/ariaqueryhandler.spec.ts
@@ -69,16 +69,19 @@ describeChromeOnly('AriaQueryHandler', (
       button = await page.$(
         'aria/[name="  Submit  button and some  spaces"][role="button"]'
       );
       await expectFound(button);
       button = await page.$(
         'aria/ignored[name="Submit  button and some  spaces"][role="button"]'
       );
       await expectFound(button);
+      await expect(page.$('aria/smth[smth="true"]')).rejects.toThrow(
+        'Unknown aria attribute "smth" in selector'
+      );
     });
   });
 
   describe('queryOne', () => {
     it('should find button by role', async () => {
       const { page } = getTestState();
       await page.setContent(
         '<div id="div"><button id="btn" role="button">Submit</button></div>'
@@ -566,17 +569,17 @@ describeChromeOnly('AriaQueryHandler', (
     it('should find treeitem by name', async () => {
       const { page } = getTestState();
       const found = await page.$$('aria/item1 item2 item3');
       const ids = await getIds(found);
       expect(ids).toEqual(['node30']);
     });
     it('should find by role "button"', async () => {
       const { page } = getTestState();
-      const found = await page.$$('aria/[role="button"]');
+      const found = await page.$$<HTMLButtonElement>('aria/[role="button"]');
       const ids = await getIds(found);
       expect(ids).toEqual(['node5', 'node6', 'node8', 'node10', 'node21']);
     });
     it('should find by role "heading"', async () => {
       const { page } = getTestState();
       const found = await page.$$('aria/[role="heading"]');
       const ids = await getIds(found);
       expect(ids).toEqual(['shown', 'node11', 'node13']);
--- a/remote/test/puppeteer/test/browsercontext.spec.ts
+++ b/remote/test/puppeteer/test/browsercontext.spec.ts
@@ -13,16 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
+  itFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 import utils from './utils.js';
 
 describe('BrowserContext', function () {
   setupTestBrowserHooks();
   it('should have default context', async () => {
     const { browser } = getTestState();
     expect(browser.browserContexts().length).toEqual(1);
--- a/remote/test/puppeteer/test/click.spec.ts
+++ b/remote/test/puppeteer/test/click.spec.ts
@@ -234,16 +234,17 @@ describe('Page.click', function () {
     ).toBe('clicked');
     await page.click('#button-80');
     expect(
       await page.evaluate(
         () => document.querySelector('#button-80').textContent
       )
     ).toBe('clicked');
   });
+  // See https://github.com/puppeteer/puppeteer/issues/7175
   it('should double click the button', async () => {
     const { page, server } = getTestState();
 
     await page.goto(server.PREFIX + '/input/button.html');
     await page.evaluate(() => {
       globalThis.double = false;
       const button = document.querySelector('button');
       button.addEventListener('dblclick', () => {
--- a/remote/test/puppeteer/test/coverage.spec.ts
+++ b/remote/test/puppeteer/test/coverage.spec.ts
@@ -235,16 +235,32 @@ describe('Coverage specs', function () {
       // trigger style recalc
       const margin = await page.evaluate(
         () => window.getComputedStyle(document.body).margin
       );
       expect(margin).toBe('10px');
       const coverage = await page.coverage.stopCSSCoverage();
       expect(coverage.length).toBe(0);
     });
+    it('should work with a recently loaded stylesheet', async () => {
+      const { page, server } = getTestState();
+
+      await page.coverage.startCSSCoverage();
+      await page.evaluate<(url: string) => Promise<void>>(async (url) => {
+        document.body.textContent = 'hello, world';
+
+        const link = document.createElement('link');
+        link.rel = 'stylesheet';
+        link.href = url;
+        document.head.appendChild(link);
+        await new Promise((x) => (link.onload = x));
+      }, server.PREFIX + '/csscoverage/stylesheet1.css');
+      const coverage = await page.coverage.stopCSSCoverage();
+      expect(coverage.length).toBe(1);
+    });
     describe('resetOnNavigation', function () {
       it('should report stylesheets across navigations', async () => {
         const { page, server } = getTestState();
 
         await page.coverage.startCSSCoverage({ resetOnNavigation: false });
         await page.goto(server.PREFIX + '/csscoverage/multiple.html');
         await page.goto(server.EMPTY_PAGE);
         const coverage = await page.coverage.stopCSSCoverage();
@@ -255,26 +271,10 @@ describe('Coverage specs', function () {
 
         await page.coverage.startCSSCoverage(); // Enabled by default.
         await page.goto(server.PREFIX + '/csscoverage/multiple.html');
         await page.goto(server.EMPTY_PAGE);
         const coverage = await page.coverage.stopCSSCoverage();
         expect(coverage.length).toBe(0);
       });
     });
-    it('should work with a recently loaded stylesheet', async () => {
-      const { page, server } = getTestState();
-
-      await page.coverage.startCSSCoverage();
-      await page.evaluate<(url: string) => Promise<void>>(async (url) => {
-        document.body.textContent = 'hello, world';
-
-        const link = document.createElement('link');
-        link.rel = 'stylesheet';
-        link.href = url;
-        document.head.appendChild(link);
-        await new Promise((x) => (link.onload = x));
-      }, server.PREFIX + '/csscoverage/stylesheet1.css');
-      const coverage = await page.coverage.stopCSSCoverage();
-      expect(coverage.length).toBe(1);
-    });
   });
 });
--- a/remote/test/puppeteer/test/dialog.spec.ts
+++ b/remote/test/puppeteer/test/dialog.spec.ts
@@ -15,16 +15,17 @@
  */
 import expect from 'expect';
 import sinon from 'sinon';
 
 import {
   getTestState,
   setupTestPageAndContextHooks,
   setupTestBrowserHooks,
+  itFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 
 describe('Page.Events.Dialog', function () {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
 
   it('should fire', async () => {
     const { page } = getTestState();
--- a/remote/test/puppeteer/test/elementhandle.spec.ts
+++ b/remote/test/puppeteer/test/elementhandle.spec.ts
@@ -15,16 +15,18 @@
  */
 
 import expect from 'expect';
 import sinon from 'sinon';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  describeFailsFirefox,
+  itFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 
 import utils from './utils.js';
 import { ElementHandle } from '../lib/cjs/puppeteer/common/JSHandle.js';
 
 describe('ElementHandle specs', function () {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
--- a/remote/test/puppeteer/test/emulation.spec.ts
+++ b/remote/test/puppeteer/test/emulation.spec.ts
@@ -14,16 +14,18 @@
  * limitations under the License.
  */
 
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  itFailsFirefox,
+  describeFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 
 describe('Emulation', () => {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
   let iPhone;
   let iPhoneLandscape;
 
--- a/remote/test/puppeteer/test/evaluation.spec.ts
+++ b/remote/test/puppeteer/test/evaluation.spec.ts
@@ -15,16 +15,18 @@
  */
 
 import utils from './utils.js';
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  itFailsFirefox,
+  describeFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 
 const bigint = typeof BigInt !== 'undefined';
 
 describe('Evaluation specs', function () {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
 
--- a/remote/test/puppeteer/test/frame.spec.ts
+++ b/remote/test/puppeteer/test/frame.spec.ts
@@ -15,16 +15,17 @@
  */
 
 import utils from './utils.js';
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  itFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 
 describe('Frame specs', function () {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
 
   describe('Frame.executionContext', function () {
     it('should work', async () => {
--- a/remote/test/puppeteer/test/idle_override.spec.ts
+++ b/remote/test/puppeteer/test/idle_override.spec.ts
@@ -14,16 +14,17 @@
  * limitations under the License.
  */
 
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  describeFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 
 describe('Emulate idle state', () => {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
 
   async function getIdleState() {
     const { page } = getTestState();
--- a/remote/test/puppeteer/test/ignorehttpserrors.spec.ts
+++ b/remote/test/puppeteer/test/ignorehttpserrors.spec.ts
@@ -10,17 +10,21 @@
  * 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.
  */
 
 import expect from 'expect';
-import { getTestState } from './mocha-utils'; // eslint-disable-line import/extensions
+import {
+  getTestState,
+  describeFailsFirefox,
+  itFailsFirefox,
+} from './mocha-utils'; // eslint-disable-line import/extensions
 
 describe('ignoreHTTPSErrors', function () {
   /* Note that this test creates its own browser rather than use
    * the one provided by the test set-up as we need one
    * with ignoreHTTPSErrors set to true
    */
   let browser;
   let context;
--- a/remote/test/puppeteer/test/input.spec.ts
+++ b/remote/test/puppeteer/test/input.spec.ts
@@ -290,17 +290,23 @@ describe('input tests', function () {
 
       await page.setContent(`<input type=file>`);
       const [fileChooser] = await Promise.all([
         page.waitForFileChooser(),
         page.$eval('input', (input: HTMLInputElement) => input.click()),
       ]);
       await fileChooser.cancel();
       let error = null;
-      await fileChooser.cancel().catch((error_) => (error = error_));
+
+      try {
+        fileChooser.cancel();
+      } catch (error_) {
+        error = error_;
+      }
+
       expect(error.message).toBe(
         'Cannot cancel FileChooser which is already handled!'
       );
     });
   });
 
   describeFailsFirefox('FileChooser.isMultiple', () => {
     it('should work for single file pick', async () => {
--- a/remote/test/puppeteer/test/jshandle.spec.ts
+++ b/remote/test/puppeteer/test/jshandle.spec.ts
@@ -14,16 +14,17 @@
  * limitations under the License.
  */
 
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  itFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 
 describe('JSHandle', function () {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
 
   describe('Page.evaluateHandle', function () {
     it('should work', async () => {
--- a/remote/test/puppeteer/test/keyboard.spec.ts
+++ b/remote/test/puppeteer/test/keyboard.spec.ts
@@ -16,16 +16,17 @@
 
 import utils from './utils.js';
 import os from 'os';
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  itFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 import { KeyInput } from '../lib/cjs/puppeteer/common/USKeyboardLayout.js';
 
 describe('Keyboard', function () {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
 
   it('should type into a textarea', async () => {
--- a/remote/test/puppeteer/test/launcher.spec.ts
+++ b/remote/test/puppeteer/test/launcher.spec.ts
@@ -13,18 +13,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 import fs from 'fs';
 import os from 'os';
 import path from 'path';
 import sinon from 'sinon';
 import { promisify } from 'util';
+import Protocol from 'devtools-protocol';
 import {
   getTestState,
+  itFailsFirefox,
   itOnlyRegularInstall,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 import utils from './utils.js';
 import expect from 'expect';
 import rimraf from 'rimraf';
 import { Page } from '../lib/cjs/puppeteer/common/Page.js';
 
 const rmAsync = promisify(rimraf);
@@ -532,16 +534,45 @@ describe('Launcher specs', function () {
         expect(error).toBe(null);
         expect(response.ok()).toBe(true);
         expect(response.securityDetails()).toBeTruthy();
         const protocol = serverRequest.socket.getProtocol().replace('v', ' ');
         expect(response.securityDetails().protocol()).toBe(protocol);
         await page.close();
         await browser.close();
       });
+      it('should support targetFilter option', async () => {
+        const { server, puppeteer, defaultBrowserOptions } = getTestState();
+
+        const originalBrowser = await puppeteer.launch(defaultBrowserOptions);
+        const browserWSEndpoint = originalBrowser.wsEndpoint();
+
+        const page1 = await originalBrowser.newPage();
+        await page1.goto(server.EMPTY_PAGE);
+
+        const page2 = await originalBrowser.newPage();
+        await page2.goto(server.EMPTY_PAGE + '?should-be-ignored');
+
+        const browser = await puppeteer.connect({
+          browserWSEndpoint,
+          targetFilter: (targetInfo: Protocol.Target.TargetInfo) =>
+            !targetInfo.url.includes('should-be-ignored'),
+        });
+
+        const pages = await browser.pages();
+
+        await page2.close();
+        await page1.close();
+        await browser.close();
+
+        expect(pages.map((p: Page) => p.url()).sort()).toEqual([
+          'about:blank',
+          server.EMPTY_PAGE,
+        ]);
+      });
       it(
         'should be able to reconnect to a disconnected browser',
         async () => {
           const { server, puppeteer, defaultBrowserOptions } = getTestState();
 
           const originalBrowser = await puppeteer.launch(defaultBrowserOptions);
           const browserWSEndpoint = originalBrowser.wsEndpoint();
           const page = await originalBrowser.newPage();
@@ -581,17 +612,16 @@ describe('Launcher specs', function () {
             ),
             browserTwo.newPage(),
           ]);
           expect(await page1.evaluate(() => 7 * 8)).toBe(56);
           expect(await page2.evaluate(() => 7 * 6)).toBe(42);
           await browserOne.close();
         }
       );
-      // @see https://github.com/puppeteer/puppeteer/issues/6527
       it('should be able to reconnect', async () => {
         const { puppeteer, server } = getTestState();
         const browserOne = await puppeteer.launch();
         const browserWSEndpoint = browserOne.wsEndpoint();
         const pageOne = await browserOne.newPage();
         await pageOne.goto(server.EMPTY_PAGE);
         browserOne.disconnect();
 
--- a/remote/test/puppeteer/test/mouse.spec.ts
+++ b/remote/test/puppeteer/test/mouse.spec.ts
@@ -14,16 +14,17 @@
  * limitations under the License.
  */
 import os from 'os';
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  itFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 import { KeyInput } from '../lib/cjs/puppeteer/common/USKeyboardLayout.js';
 
 interface Dimensions {
   x: number;
   y: number;
   width: number;
   height: number;
--- a/remote/test/puppeteer/test/navigation.spec.ts
+++ b/remote/test/puppeteer/test/navigation.spec.ts
@@ -15,16 +15,18 @@
  */
 
 import utils from './utils.js';
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  itFailsFirefox,
+  describeFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 import os from 'os';
 
 describe('navigation', function () {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
   describe('Page.goto', function () {
     it('should work', async () => {
--- a/remote/test/puppeteer/test/network.spec.ts
+++ b/remote/test/puppeteer/test/network.spec.ts
@@ -17,16 +17,18 @@
 import fs from 'fs';
 import path from 'path';
 import utils from './utils.js';
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  itFailsFirefox,
+  describeFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 
 describe('network', function () {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
 
   describe('Page.Events.Request', function () {
     it('should fire for navigation requests', async () => {
@@ -348,16 +350,30 @@ describe('network', function () {
       expect(requests.length).toBe(1);
       expect(requests[0].url()).toBe(server.EMPTY_PAGE);
       expect(requests[0].resourceType()).toBe('document');
       expect(requests[0].method()).toBe('GET');
       expect(requests[0].response()).toBeTruthy();
       expect(requests[0].frame() === page.mainFrame()).toBe(true);
       expect(requests[0].frame().url()).toBe(server.EMPTY_PAGE);
     });
+    it('Page.Events.RequestServedFromCache', async () => {
+      const { page, server } = getTestState();
+
+      const cached = [];
+      page.on('requestservedfromcache', (r) =>
+        cached.push(r.url().split('/').pop())
+      );
+
+      await page.goto(server.PREFIX + '/cached/one-style.html');
+      expect(cached).toEqual([]);
+
+      await page.reload();
+      expect(cached).toEqual(['one-style.css']);
+    });
     it('Page.Events.Response', async () => {
       const { page, server } = getTestState();
 
       const responses = [];
       page.on('response', (response) => responses.push(response));
       await page.goto(server.EMPTY_PAGE);
       expect(responses.length).toBe(1);
       expect(responses[0].url()).toBe(server.EMPTY_PAGE);
@@ -562,10 +578,33 @@ describe('network', function () {
       });
       let response = await page.goto(server.EMPTY_PAGE);
       expect(response.status()).toBe(200);
       await page.authenticate(null);
       // Navigate to a different origin to bust Chrome's credential caching.
       response = await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html');
       expect(response.status()).toBe(401);
     });
+    it('should not disable caching', async () => {
+      const { page, server } = getTestState();
+
+      // Use unique user/password since Chrome caches credentials per origin.
+      server.setAuth('/cached/one-style.css', 'user4', 'pass4');
+      server.setAuth('/cached/one-style.html', 'user4', 'pass4');
+      await page.authenticate({
+        username: 'user4',
+        password: 'pass4',
+      });
+
+      const responses = new Map();
+      page.on('response', (r) => responses.set(r.url().split('/').pop(), r));
+
+      // Load and re-load to make sure it's cached.
+      await page.goto(server.PREFIX + '/cached/one-style.html');
+      await page.reload();
+
+      expect(responses.get('one-style.css').status()).toBe(200);
+      expect(responses.get('one-style.css').fromCache()).toBe(true);
+      expect(responses.get('one-style.html').status()).toBe(304);
+      expect(responses.get('one-style.html').fromCache()).toBe(false);
+    });
   });
 });
--- a/remote/test/puppeteer/test/page.spec.ts
+++ b/remote/test/puppeteer/test/page.spec.ts
@@ -16,19 +16,20 @@
 import fs from 'fs';
 import path from 'path';
 import utils from './utils.js';
 const { waitEvent } = utils;
 import expect from 'expect';
 import sinon from 'sinon';
 import {
   getTestState,
-  itFailsFirefox,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  itFailsFirefox,
+  describeFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 import { Page, Metrics } from '../lib/cjs/puppeteer/common/Page.js';
 import { JSHandle } from '../lib/cjs/puppeteer/common/JSHandle.js';
 
 describe('Page', function () {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
   describe('Page.close', function () {
--- a/remote/test/puppeteer/test/requestinterception.spec.ts
+++ b/remote/test/puppeteer/test/requestinterception.spec.ts
@@ -17,16 +17,17 @@
 import fs from 'fs';
 import path from 'path';
 import utils from './utils.js';
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  describeFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 
 describe('request interception', function () {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
   describe('Page.setRequestInterception', function () {
     it('should intercept', async () => {
       const { page, server } = getTestState();
@@ -489,16 +490,46 @@ describe('request interception', functio
       });
       await page.goto(
         pathToFileURL(path.join(__dirname, 'assets', 'one-style.html'))
       );
       expect(urls.size).toBe(2);
       expect(urls.has('one-style.html')).toBe(true);
       expect(urls.has('one-style.css')).toBe(true);
     });
+    it('should not cache if not cache-safe', async () => {
+      const { page, server } = getTestState();
+
+      // Load and re-load to make sure it's cached.
+      await page.goto(server.PREFIX + '/cached/one-style.html');
+
+      await page.setRequestInterception(true, false);
+      page.on('request', (request) => request.continue());
+
+      const cached = [];
+      page.on('requestservedfromcache', (r) => cached.push(r));
+
+      await page.reload();
+      expect(cached.length).toBe(0);
+    });
+    it('should cache if cache-safe', async () => {
+      const { page, server } = getTestState();
+
+      // Load and re-load to make sure it's cached.
+      await page.goto(server.PREFIX + '/cached/one-style.html');
+
+      await page.setRequestInterception(true, true);
+      page.on('request', (request) => request.continue());
+
+      const cached = [];
+      page.on('requestservedfromcache', (r) => cached.push(r));
+
+      await page.reload();
+      expect(cached.length).toBe(1);
+    });
   });
 
   describe('Request.continue', function () {
     it('should work', async () => {
       const { page, server } = getTestState();
 
       await page.setRequestInterception(true);
       page.on('request', (request) => request.continue());
--- a/remote/test/puppeteer/test/screenshot.spec.ts
+++ b/remote/test/puppeteer/test/screenshot.spec.ts
@@ -14,16 +14,17 @@
  * limitations under the License.
  */
 
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  itFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 
 describe('Screenshots', function () {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
 
   describe('Page.screenshot', function () {
     it('should work', async () => {
--- a/remote/test/puppeteer/test/target.spec.ts
+++ b/remote/test/puppeteer/test/target.spec.ts
@@ -16,16 +16,17 @@
 
 import utils from './utils.js';
 const { waitEvent } = utils;
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  itFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 import { Target } from '../lib/cjs/puppeteer/common/Target.js';
 
 describe('Target', function () {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
 
   it('Browser.targets should return all of the targets', async () => {
@@ -42,17 +43,16 @@ describe('Target', function () {
   });
   it('Browser.pages should return all of the pages', async () => {
     const { page, context } = getTestState();
 
     // The pages will be the testing page
     const allPages = await context.pages();
     expect(allPages.length).toBe(1);
     expect(allPages).toContain(page);
-    expect(allPages[0]).not.toBe(allPages[1]);
   });
   it('should contain browser target', async () => {
     const { browser } = getTestState();
 
     const targets = browser.targets();
     const browserTarget = targets.find((target) => target.type() === 'browser');
     expect(browserTarget).toBeTruthy();
   });
--- a/remote/test/puppeteer/test/touchscreen.spec.ts
+++ b/remote/test/puppeteer/test/touchscreen.spec.ts
@@ -14,16 +14,17 @@
  * limitations under the License.
  */
 
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  describeFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 
 describe('Touchscreen', function () {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
 
   it('should tap the button', async () => {
     const { puppeteer, page, server } = getTestState();
--- a/remote/test/puppeteer/test/waittask.spec.ts
+++ b/remote/test/puppeteer/test/waittask.spec.ts
@@ -16,16 +16,17 @@
 
 import utils from './utils.js';
 import sinon from 'sinon';
 import expect from 'expect';
 import {
   getTestState,
   setupTestBrowserHooks,
   setupTestPageAndContextHooks,
+  itFailsFirefox,
 } from './mocha-utils'; // eslint-disable-line import/extensions
 
 describe('waittask specs', function () {
   setupTestBrowserHooks();
   setupTestPageAndContextHooks();
 
   describe('Page.waitFor', function () {
     /* This method is deprecated but we don't want the warnings showing up in
--- a/remote/test/puppeteer/utils/doclint/README.md
+++ b/remote/test/puppeteer/utils/doclint/README.md
@@ -1,23 +1,19 @@
 # DocLint
 
-**Doclint** is a small program that lints Puppeteer's documentation against
-Puppeteer's source code.
+**Doclint** is a small program that lints Puppeteer's documentation against Puppeteer's source code.
 
 Doclint works in a few steps:
 
-1. Read sources in `lib/` folder, parse AST trees and extract public API
-    - note that we run DocLint on the outputted JavaScript in `lib/` rather than the source code in `src/`. We will do this until we have migrated `src/` to be exclusively TypeScript and then we can update DocLint to support TypeScript.
-2. Read sources in `docs/` folder, render markdown to HTML, use puppeteer to traverse the HTML
-  and extract described API
-3. Compare one API to another
+1. Read sources in `lib/` folder, parse AST trees and extract public API. Note that we run DocLint on the outputted JavaScript in `lib/` rather than the source code in `src/`. We will do this until we have migrated `src/` to be exclusively TypeScript and then we can update DocLint to support TypeScript.
+2. Read sources in `docs/` folder, render markdown to HTML, use puppeteer to traverse the HTML and extract described API.
+3. Compare one API to another.
 
-Doclint is also responsible for general markdown checks, most notably for the table of contents
-relevancy.
+Doclint is also responsible for general markdown checks, most notably for the table of contents relevancy.
 
 ## Running
 
 ```bash
 npm run doc
 ```
 
 ## Tests
--- a/remote/test/puppeteer/utils/doclint/check_public_api/index.js
+++ b/remote/test/puppeteer/utils/doclint/check_public_api/index.js
@@ -859,16 +859,37 @@ function compareDocumentations(actual, e
       ],
       [
         'Method BrowserContext.overridePermissions() permissions',
         {
           actualName: 'Array<string>',
           expectedName: 'Array<Permission>',
         },
       ],
+      [
+        'Method HTTPRequest.respond() response.body',
+        {
+          actualName: 'string|Buffer',
+          expectedName: 'Object',
+        },
+      ],
+      [
+        'Method HTTPRequest.respond() response.contentType',
+        {
+          actualName: 'string',
+          expectedName: 'Object',
+        },
+      ],
+      [
+        'Method HTTPRequest.respond() response.status',
+        {
+          actualName: 'number',
+          expectedName: 'Object',
+        },
+      ],
     ]);
 
     const expectedForSource = expectedNamingMismatches.get(source);
     if (!expectedForSource) return false;
 
     const namingMismatchIsExpected =
       expectedForSource.actualName === actualName &&
       expectedForSource.expectedName === expectedName;
--- a/remote/test/puppeteer/vendor/mitt/src/index.ts
+++ b/remote/test/puppeteer/vendor/mitt/src/index.ts
@@ -1,12 +1,19 @@
+
+/**
+ * @public
+ */
 export type EventType = string | symbol;
 
 // An event handler can take an optional event argument
 // and should not return a value
+/**
+ * @public
+ */
 export type Handler<T = any> = (event?: T) => void;
 export type WildcardHandler = (type: EventType, event?: any) => void;
 
 // An array of all currently registered event handlers for a type
 export type EventHandlerList = Array<Handler>;
 export type WildCardEventHandlerList = Array<WildcardHandler>;
 
 // A map of event types and their corresponding event handlers.
--- a/remote/test/puppeteer/versions.js
+++ b/remote/test/puppeteer/versions.js
@@ -12,16 +12,18 @@
  * 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.
  */
 
 const versionsPerRelease = new Map([
   // This is a mapping from Chromium version => Puppeteer version.
   // In Chromium roll patches, use 'NEXT' for the Puppeteer version.
+  ['91.0.4469.0', 'v9.0.0'],
+  ['90.0.4427.0', 'v8.0.0'],
   ['90.0.4403.0', 'v7.0.0'],
   ['89.0.4389.0', 'v6.0.0'],
   ['88.0.4298.0', 'v5.5.0'],
   ['87.0.4272.0', 'v5.4.0'],
   ['86.0.4240.0', 'v5.3.0'],
   ['85.0.4182.0', 'v5.2.1'],
   ['84.0.4147.0', 'v5.1.0'],
   ['83.0.4103.0', 'v3.1.0'],