diff --git a/node_modules/.gitignore b/node_modules/.gitignore index fefb3224eb1d0..9a1cd16e32bd0 100644 --- a/node_modules/.gitignore +++ b/node_modules/.gitignore @@ -27,6 +27,8 @@ package-lock.json /@babel/types /@blueoak/list /@eslint/eslintrc +/@istanbuljs/load-nyc-config +/@istanbuljs/schema /@mdx-js/mdx /@mdx-js/util /@types/hast @@ -42,7 +44,6 @@ package-lock.json /ansi-colors /anymatch /append-transform -/arg /argparse /array-find-index /array-includes @@ -81,7 +82,6 @@ package-lock.json /convert-source-map /correct-license-metadata /coveralls -/cp-file /cross-spawn /cssom /cssstyle @@ -95,7 +95,6 @@ package-lock.json /define-properties /detab /detect-libc -/diff-frag /docopt /doctrine /domexception @@ -118,7 +117,6 @@ package-lock.json /eslint-scope /eslint-utils /eslint-visitor-keys -/esm /espree /esprima /esquery @@ -136,9 +134,8 @@ package-lock.json /findit /flat-cache /flatted -/flow-parser -/flow-remove-types /foreground-child +/fromentries /fs-access /fs-constants /fs-exists-cached @@ -148,6 +145,7 @@ package-lock.json /gensync /get-caller-file /get-intrinsic +/get-package-type /github-from-package /glob-parent /globals @@ -190,6 +188,7 @@ package-lock.json /is-string /is-symbol /is-whitespace-character +/is-windows /is-word-character /istanbul-lib-coverage /istanbul-lib-hook @@ -203,22 +202,24 @@ package-lock.json /js-yaml /jsdom /jsesc -/json-parse-better-errors /json-parse-errback /json-stable-stringify-without-jsonify /json5 /lcov-parse /levn +/libtap /licensee /load-json-file /locate-path /lodash +/lodash.clonedeep +/lodash.flatten /lodash.flattendeep +/lodash.truncate /lodash.uniq /log-driver /loose-envify /make-dir -/make-error /markdown-escapes /marked /marked-man @@ -226,17 +227,14 @@ package-lock.json /mdast-util-definitions /mdast-util-to-hast /mdurl -/merge-source-map /mimic-response /minimist /mkdirp-classic /napi-build-utils /natural-compare -/nested-error-stacks -/nice-try /node-abi /node-addon-api -/node-modules-regexp +/node-preload /noop-logger /normalize-path /npm-license-corrections @@ -249,7 +247,6 @@ package-lock.json /object.getownpropertydescriptors /object.values /optionator -/os-homedir /own-or /own-or-env /p-limit @@ -265,14 +262,13 @@ package-lock.json /path-type /picomatch /pify -/pirates /pkg-dir /prebuild-install /prelude-ls +/process-on-spawn /progress /prop-types /property-information -/pseudomap /pump /queue-microtask /rc @@ -339,11 +335,9 @@ package-lock.json /trim-trailing-lines /trivial-deferred /trough -/ts-node /tsconfig-paths /type-check /type-fest -/typescript /unbox-primitive /unherit /unicode-length @@ -363,7 +357,6 @@ package-lock.json /vfile /vfile-location /vfile-message -/vlq /w3c-hr-time /w3c-xmlserializer /web-namespaces @@ -373,7 +366,6 @@ package-lock.json /whatwg-url /which-boxed-primitive /which-module -/which-pm-runs /word-wrap /wrap-ansi /ws @@ -385,5 +377,4 @@ package-lock.json /yapool /yargs /yargs-parser -/yn /zwitch diff --git a/node_modules/@istanbuljs/load-nyc-config/CHANGELOG.md b/node_modules/@istanbuljs/load-nyc-config/CHANGELOG.md new file mode 100644 index 0000000000000..980719efe31b0 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/CHANGELOG.md @@ -0,0 +1,41 @@ +# 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. + +## [1.1.0](https://github.com/istanbuljs/load-nyc-config/compare/v1.0.0...v1.1.0) (2020-05-20) + + +### Features + +* Create `isLoading` function ([#15](https://github.com/istanbuljs/load-nyc-config/issues/15)) ([0e58b51](https://github.com/istanbuljs/load-nyc-config/commit/0e58b516f663af7ed710ba27f2090fc28bc3fdb1)) +* Support loading ES module config from `.js` files ([#14](https://github.com/istanbuljs/load-nyc-config/issues/14)) ([b1ea369](https://github.com/istanbuljs/load-nyc-config/commit/b1ea369f1e5162133b7057c5e3fefb8085671ab3)) + +## [1.0.0](https://github.com/istanbuljs/load-nyc-config/compare/v1.0.0-alpha.2...v1.0.0) (2019-12-20) + + +### Features + +* Version bump only ([#11](https://github.com/istanbuljs/load-nyc-config/issues/11)) ([8c3f1be](https://github.com/istanbuljs/load-nyc-config/commit/8c3f1be8d4d30161088a79878c02210db4c2fbfb)) + +## [1.0.0-alpha.2](https://github.com/istanbuljs/load-nyc-config/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) (2019-11-24) + + +### Bug Fixes + +* Remove support for loading .js config under `type: 'module'` ([#10](https://github.com/istanbuljs/load-nyc-config/issues/10)) ([420fe87](https://github.com/istanbuljs/load-nyc-config/commit/420fe87da7dde3e9d98ef07f0a8a03d2b4d1dcb1)) +* Resolve cwd per config that sets it ([#9](https://github.com/istanbuljs/load-nyc-config/issues/9)) ([649efdc](https://github.com/istanbuljs/load-nyc-config/commit/649efdcda405c476764eebcf15af5da542fb21e1)) + +## [1.0.0-alpha.1](https://github.com/istanbuljs/load-nyc-config/compare/v1.0.0-alpha.0...v1.0.0-alpha.1) (2019-10-08) + + +### Bug Fixes + +* Add `cwd` to returned config object ([#8](https://github.com/istanbuljs/load-nyc-config/issues/8)) ([cb5184a](https://github.com/istanbuljs/load-nyc-config/commit/cb5184a)) + +## 1.0.0-alpha.0 (2019-10-06) + + +### Features + +* Add support for loading config from ESM modules ([#7](https://github.com/istanbuljs/load-nyc-config/issues/7)) ([bc5ea3e](https://github.com/istanbuljs/load-nyc-config/commit/bc5ea3e)), closes [#6](https://github.com/istanbuljs/load-nyc-config/issues/6) +* Initial implementation ([ff90134](https://github.com/istanbuljs/load-nyc-config/commit/ff90134)) diff --git a/node_modules/@istanbuljs/load-nyc-config/LICENSE b/node_modules/@istanbuljs/load-nyc-config/LICENSE new file mode 100644 index 0000000000000..345e587a15f4f --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/LICENSE @@ -0,0 +1,16 @@ +ISC License + +Copyright (c) 2019, Contributors + +Permission to use, copy, modify, and/or distribute this software +for any purpose with or without fee is hereby granted, provided +that the above copyright notice and this permission notice +appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE +LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/@istanbuljs/load-nyc-config/README.md b/node_modules/@istanbuljs/load-nyc-config/README.md new file mode 100644 index 0000000000000..533db741c6241 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/README.md @@ -0,0 +1,64 @@ +# @istanbuljs/load-nyc-config + +The utility function which NYC uses to load configuration. +This can be used by outside programs to calculate the configuration. +Command-line arguments are not considered by this function. + +```js +const {loadNycConfig} = require('@istanbuljs/load-nyc-config'); + +(async () { + console.log(await loadNycConfig()); +})(); +``` + +## loadNycConfig([options]) + +### options.cwd + +Type: `string` +Default: `cwd` from parent nyc process or `process.cwd()` + +### options.nycrcPath + +Type: `string` +Default: `undefined` + +Name of the file containing nyc configuration. +This can be a relative or absolute path. +Relative paths can exist at `options.cwd` or any parent directory. +If an nycrc is specified but cannot be found an exception is thrown. + +If no nycrc option is provided the default priority of config files are: + +* .nycrc +* .nycrc.json +* .nycrc.yml +* .nycrc.yaml +* nyc.config.js +* nyc.config.cjs +* nyc.config.mjs + +## Configuration merging + +Configuration is first loaded from `package.json` if found, this serves as the package +defaults. These options can be overridden by an nycrc if found. Arrays are not merged, +so if `package.json` sets `"require": ["@babel/register"]` and `.nycrc` sets `"require": ["esm"]` +the effective require setting will only include `"esm"`. + +## isLoading + +```js +const {isLoading} = require('@istanbuljs/load-nyc-config'); + +console.log(isLoading()); +``` + +In some cases source transformation hooks can get installed before the configuration is +loaded. This allows hooks to ignore source loads that occur during configuration load. + +## `@istanbuljs/load-nyc-config` for enterprise + +Available as part of the Tidelift Subscription. + +The maintainers of `@istanbuljs/load-nyc-config` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-istanbuljs-load-nyc-config?utm_source=npm-istanbuljs-load-nyc-config&utm_medium=referral&utm_campaign=enterprise) diff --git a/node_modules/@istanbuljs/load-nyc-config/index.js b/node_modules/@istanbuljs/load-nyc-config/index.js new file mode 100644 index 0000000000000..0c8c05e581194 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/index.js @@ -0,0 +1,166 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const {promisify} = require('util'); +const camelcase = require('camelcase'); +const findUp = require('find-up'); +const resolveFrom = require('resolve-from'); +const getPackageType = require('get-package-type'); + +const readFile = promisify(fs.readFile); + +let loadActive = false; + +function isLoading() { + return loadActive; +} + +const standardConfigFiles = [ + '.nycrc', + '.nycrc.json', + '.nycrc.yml', + '.nycrc.yaml', + 'nyc.config.js', + 'nyc.config.cjs', + 'nyc.config.mjs' +]; + +function camelcasedConfig(config) { + const results = {}; + for (const [field, value] of Object.entries(config)) { + results[camelcase(field)] = value; + } + + return results; +} + +async function findPackage(options) { + const cwd = options.cwd || process.env.NYC_CWD || process.cwd(); + const pkgPath = await findUp('package.json', {cwd}); + if (pkgPath) { + const pkgConfig = JSON.parse(await readFile(pkgPath, 'utf8')).nyc || {}; + if ('cwd' in pkgConfig) { + pkgConfig.cwd = path.resolve(path.dirname(pkgPath), pkgConfig.cwd); + } + + return { + cwd: path.dirname(pkgPath), + pkgConfig + }; + } + + return { + cwd, + pkgConfig: {} + }; +} + +async function actualLoad(configFile) { + if (!configFile) { + return {}; + } + + const configExt = path.extname(configFile).toLowerCase(); + switch (configExt) { + case '.js': + /* istanbul ignore next: coverage for 13.2.0+ is shown in load-esm.js */ + if (await getPackageType(configFile) === 'module') { + return require('./load-esm')(configFile); + } + + /* fallthrough */ + case '.cjs': + return require(configFile); + /* istanbul ignore next: coverage for 13.2.0+ is shown in load-esm.js */ + case '.mjs': + return require('./load-esm')(configFile); + case '.yml': + case '.yaml': + return require('js-yaml').load(await readFile(configFile, 'utf8')); + default: + return JSON.parse(await readFile(configFile, 'utf8')); + } +} + +async function loadFile(configFile) { + /* This lets @istanbuljs/esm-loader-hook avoid circular initialization when loading + * configuration. This should generally only happen when the loader hook is active + * on the main nyc process. */ + loadActive = true; + + try { + return await actualLoad(configFile); + } finally { + loadActive = false; + } +} + +async function applyExtends(config, filename, loopCheck = new Set()) { + config = camelcasedConfig(config); + if ('extends' in config) { + const extConfigs = [].concat(config.extends); + if (extConfigs.some(e => typeof e !== 'string')) { + throw new TypeError(`${filename} contains an invalid 'extends' option`); + } + + delete config.extends; + const filePath = path.dirname(filename); + for (const extConfig of extConfigs) { + const configFile = resolveFrom.silent(filePath, extConfig) || + resolveFrom.silent(filePath, './' + extConfig); + if (!configFile) { + throw new Error(`Could not resolve configuration file ${extConfig} from ${path.dirname(filename)}.`); + } + + if (loopCheck.has(configFile)) { + throw new Error(`Circular extended configurations: '${configFile}'.`); + } + + loopCheck.add(configFile); + + // eslint-disable-next-line no-await-in-loop + const configLoaded = await loadFile(configFile); + if ('cwd' in configLoaded) { + configLoaded.cwd = path.resolve(path.dirname(configFile), configLoaded.cwd); + } + + Object.assign( + config, + // eslint-disable-next-line no-await-in-loop + await applyExtends(configLoaded, configFile, loopCheck) + ); + } + } + + return config; +} + +async function loadNycConfig(options = {}) { + const {cwd, pkgConfig} = await findPackage(options); + const configFiles = [].concat(options.nycrcPath || standardConfigFiles); + const configFile = await findUp(configFiles, {cwd}); + if (options.nycrcPath && !configFile) { + throw new Error(`Requested configuration file ${options.nycrcPath} not found`); + } + + const config = { + cwd, + ...(await applyExtends(pkgConfig, path.join(cwd, 'package.json'))), + ...(await applyExtends(await loadFile(configFile), configFile)) + }; + + const arrayFields = ['require', 'extension', 'exclude', 'include']; + for (const arrayField of arrayFields) { + if (config[arrayField]) { + config[arrayField] = [].concat(config[arrayField]); + } + } + + return config; +} + +module.exports = { + loadNycConfig, + isLoading +}; diff --git a/node_modules/@istanbuljs/load-nyc-config/load-esm.js b/node_modules/@istanbuljs/load-nyc-config/load-esm.js new file mode 100644 index 0000000000000..0eb517e6b7bc6 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/load-esm.js @@ -0,0 +1,12 @@ +'use strict'; + +const {pathToFileURL} = require('url'); + +module.exports = async filename => { + const mod = await import(pathToFileURL(filename)); + if ('default' in mod === false) { + throw new Error(`${filename} has no default export`); + } + + return mod.default; +}; diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/index.d.ts b/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/index.d.ts new file mode 100644 index 0000000000000..41e3192ae9f3a --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/index.d.ts @@ -0,0 +1,137 @@ +import {Options as LocatePathOptions} from 'locate-path'; + +declare const stop: unique symbol; + +declare namespace findUp { + interface Options extends LocatePathOptions {} + + type StopSymbol = typeof stop; + + type Match = string | StopSymbol | undefined; +} + +declare const findUp: { + /** + Find a file or directory by walking up parent directories. + + @param name - Name of the file or directory to find. Can be multiple. + @returns The first path found (by respecting the order of `name`s) or `undefined` if none could be found. + + @example + ``` + // / + // └── Users + // └── sindresorhus + // ├── unicorn.png + // └── foo + // └── bar + // ├── baz + // └── example.js + + // example.js + import findUp = require('find-up'); + + (async () => { + console.log(await findUp('unicorn.png')); + //=> '/Users/sindresorhus/unicorn.png' + + console.log(await findUp(['rainbow.png', 'unicorn.png'])); + //=> '/Users/sindresorhus/unicorn.png' + })(); + ``` + */ + (name: string | string[], options?: findUp.Options): Promise; + + /** + Find a file or directory by walking up parent directories. + + @param matcher - Called for each directory in the search. Return a path or `findUp.stop` to stop the search. + @returns The first path found or `undefined` if none could be found. + + @example + ``` + import path = require('path'); + import findUp = require('find-up'); + + (async () => { + console.log(await findUp(async directory => { + const hasUnicorns = await findUp.exists(path.join(directory, 'unicorn.png')); + return hasUnicorns && directory; + }, {type: 'directory'})); + //=> '/Users/sindresorhus' + })(); + ``` + */ + (matcher: (directory: string) => (findUp.Match | Promise), options?: findUp.Options): Promise; + + sync: { + /** + Synchronously find a file or directory by walking up parent directories. + + @param name - Name of the file or directory to find. Can be multiple. + @returns The first path found (by respecting the order of `name`s) or `undefined` if none could be found. + */ + (name: string | string[], options?: findUp.Options): string | undefined; + + /** + Synchronously find a file or directory by walking up parent directories. + + @param matcher - Called for each directory in the search. Return a path or `findUp.stop` to stop the search. + @returns The first path found or `undefined` if none could be found. + + @example + ``` + import path = require('path'); + import findUp = require('find-up'); + + console.log(findUp.sync(directory => { + const hasUnicorns = findUp.sync.exists(path.join(directory, 'unicorn.png')); + return hasUnicorns && directory; + }, {type: 'directory'})); + //=> '/Users/sindresorhus' + ``` + */ + (matcher: (directory: string) => findUp.Match, options?: findUp.Options): string | undefined; + + /** + Synchronously check if a path exists. + + @param path - Path to the file or directory. + @returns Whether the path exists. + + @example + ``` + import findUp = require('find-up'); + + console.log(findUp.sync.exists('/Users/sindresorhus/unicorn.png')); + //=> true + ``` + */ + exists(path: string): boolean; + } + + /** + Check if a path exists. + + @param path - Path to a file or directory. + @returns Whether the path exists. + + @example + ``` + import findUp = require('find-up'); + + (async () => { + console.log(await findUp.exists('/Users/sindresorhus/unicorn.png')); + //=> true + })(); + ``` + */ + exists(path: string): Promise; + + /** + Return this in a `matcher` function to stop the search and force `findUp` to immediately return `undefined`. + */ + readonly stop: findUp.StopSymbol; +}; + +export = findUp; diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/index.js b/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/index.js new file mode 100644 index 0000000000000..ce564e5d32284 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/index.js @@ -0,0 +1,89 @@ +'use strict'; +const path = require('path'); +const locatePath = require('locate-path'); +const pathExists = require('path-exists'); + +const stop = Symbol('findUp.stop'); + +module.exports = async (name, options = {}) => { + let directory = path.resolve(options.cwd || ''); + const {root} = path.parse(directory); + const paths = [].concat(name); + + const runMatcher = async locateOptions => { + if (typeof name !== 'function') { + return locatePath(paths, locateOptions); + } + + const foundPath = await name(locateOptions.cwd); + if (typeof foundPath === 'string') { + return locatePath([foundPath], locateOptions); + } + + return foundPath; + }; + + // eslint-disable-next-line no-constant-condition + while (true) { + // eslint-disable-next-line no-await-in-loop + const foundPath = await runMatcher({...options, cwd: directory}); + + if (foundPath === stop) { + return; + } + + if (foundPath) { + return path.resolve(directory, foundPath); + } + + if (directory === root) { + return; + } + + directory = path.dirname(directory); + } +}; + +module.exports.sync = (name, options = {}) => { + let directory = path.resolve(options.cwd || ''); + const {root} = path.parse(directory); + const paths = [].concat(name); + + const runMatcher = locateOptions => { + if (typeof name !== 'function') { + return locatePath.sync(paths, locateOptions); + } + + const foundPath = name(locateOptions.cwd); + if (typeof foundPath === 'string') { + return locatePath.sync([foundPath], locateOptions); + } + + return foundPath; + }; + + // eslint-disable-next-line no-constant-condition + while (true) { + const foundPath = runMatcher({...options, cwd: directory}); + + if (foundPath === stop) { + return; + } + + if (foundPath) { + return path.resolve(directory, foundPath); + } + + if (directory === root) { + return; + } + + directory = path.dirname(directory); + } +}; + +module.exports.exists = pathExists; + +module.exports.sync.exists = pathExists.sync; + +module.exports.stop = stop; diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/license b/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/license new file mode 100644 index 0000000000000..e7af2f77107d7 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/package.json b/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/package.json new file mode 100644 index 0000000000000..cd50281eb29a9 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/package.json @@ -0,0 +1,53 @@ +{ + "name": "find-up", + "version": "4.1.0", + "description": "Find a file or directory by walking up parent directories", + "license": "MIT", + "repository": "sindresorhus/find-up", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "find", + "up", + "find-up", + "findup", + "look-up", + "look", + "file", + "search", + "match", + "package", + "resolve", + "parent", + "parents", + "folder", + "directory", + "walk", + "walking", + "path" + ], + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "devDependencies": { + "ava": "^2.1.0", + "is-path-inside": "^2.1.0", + "tempy": "^0.3.0", + "tsd": "^0.7.3", + "xo": "^0.24.0" + } +} diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/readme.md b/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/readme.md new file mode 100644 index 0000000000000..d6a21e525988e --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/find-up/readme.md @@ -0,0 +1,156 @@ +# find-up [![Build Status](https://travis-ci.org/sindresorhus/find-up.svg?branch=master)](https://travis-ci.org/sindresorhus/find-up) + +> Find a file or directory by walking up parent directories + + +## Install + +``` +$ npm install find-up +``` + + +## Usage + +``` +/ +└── Users + └── sindresorhus + ├── unicorn.png + └── foo + └── bar + ├── baz + └── example.js +``` + +`example.js` + +```js +const path = require('path'); +const findUp = require('find-up'); + +(async () => { + console.log(await findUp('unicorn.png')); + //=> '/Users/sindresorhus/unicorn.png' + + console.log(await findUp(['rainbow.png', 'unicorn.png'])); + //=> '/Users/sindresorhus/unicorn.png' + + console.log(await findUp(async directory => { + const hasUnicorns = await findUp.exists(path.join(directory, 'unicorn.png')); + return hasUnicorns && directory; + }, {type: 'directory'})); + //=> '/Users/sindresorhus' +})(); +``` + + +## API + +### findUp(name, options?) +### findUp(matcher, options?) + +Returns a `Promise` for either the path or `undefined` if it couldn't be found. + +### findUp([...name], options?) + +Returns a `Promise` for either the first path found (by respecting the order of the array) or `undefined` if none could be found. + +### findUp.sync(name, options?) +### findUp.sync(matcher, options?) + +Returns a path or `undefined` if it couldn't be found. + +### findUp.sync([...name], options?) + +Returns the first path found (by respecting the order of the array) or `undefined` if none could be found. + +#### name + +Type: `string` + +Name of the file or directory to find. + +#### matcher + +Type: `Function` + +A function that will be called with each directory until it returns a `string` with the path, which stops the search, or the root directory has been reached and nothing was found. Useful if you want to match files with certain patterns, set of permissions, or other advanced use-cases. + +When using async mode, the `matcher` may optionally be an async or promise-returning function that returns the path. + +#### options + +Type: `object` + +##### cwd + +Type: `string`
+Default: `process.cwd()` + +Directory to start from. + +##### type + +Type: `string`
+Default: `'file'`
+Values: `'file'` `'directory'` + +The type of paths that can match. + +##### allowSymlinks + +Type: `boolean`
+Default: `true` + +Allow symbolic links to match if they point to the chosen path type. + +### findUp.exists(path) + +Returns a `Promise` of whether the path exists. + +### findUp.sync.exists(path) + +Returns a `boolean` of whether the path exists. + +#### path + +Type: `string` + +Path to a file or directory. + +### findUp.stop + +A [`Symbol`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol) that can be returned by a `matcher` function to stop the search and cause `findUp` to immediately return `undefined`. Useful as a performance optimization in case the current working directory is deeply nested in the filesystem. + +```js +const path = require('path'); +const findUp = require('find-up'); + +(async () => { + await findUp(directory => { + return path.basename(directory) === 'work' ? findUp.stop : 'logo.png'; + }); +})(); +``` + + +## Related + +- [find-up-cli](https://github.com/sindresorhus/find-up-cli) - CLI for this module +- [pkg-up](https://github.com/sindresorhus/pkg-up) - Find the closest package.json file +- [pkg-dir](https://github.com/sindresorhus/pkg-dir) - Find the root directory of an npm package +- [resolve-from](https://github.com/sindresorhus/resolve-from) - Resolve the path of a module like `require.resolve()` but from a given path + + +--- + +
+ + Get professional support for 'find-up' with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/index.d.ts b/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/index.d.ts new file mode 100644 index 0000000000000..fbde526c0ab23 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/index.d.ts @@ -0,0 +1,83 @@ +declare namespace locatePath { + interface Options { + /** + Current working directory. + + @default process.cwd() + */ + readonly cwd?: string; + + /** + Type of path to match. + + @default 'file' + */ + readonly type?: 'file' | 'directory'; + + /** + Allow symbolic links to match if they point to the requested path type. + + @default true + */ + readonly allowSymlinks?: boolean; + } + + interface AsyncOptions extends Options { + /** + Number of concurrently pending promises. Minimum: `1`. + + @default Infinity + */ + readonly concurrency?: number; + + /** + Preserve `paths` order when searching. + + Disable this to improve performance if you don't care about the order. + + @default true + */ + readonly preserveOrder?: boolean; + } +} + +declare const locatePath: { + /** + Get the first path that exists on disk of multiple paths. + + @param paths - Paths to check. + @returns The first path that exists or `undefined` if none exists. + + @example + ``` + import locatePath = require('locate-path'); + + const files = [ + 'unicorn.png', + 'rainbow.png', // Only this one actually exists on disk + 'pony.png' + ]; + + (async () => { + console(await locatePath(files)); + //=> 'rainbow' + })(); + ``` + */ + (paths: Iterable, options?: locatePath.AsyncOptions): Promise< + string | undefined + >; + + /** + Synchronously get the first path that exists on disk of multiple paths. + + @param paths - Paths to check. + @returns The first path that exists or `undefined` if none exists. + */ + sync( + paths: Iterable, + options?: locatePath.Options + ): string | undefined; +}; + +export = locatePath; diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/index.js b/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/index.js new file mode 100644 index 0000000000000..4604bbf4015c4 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/index.js @@ -0,0 +1,65 @@ +'use strict'; +const path = require('path'); +const fs = require('fs'); +const {promisify} = require('util'); +const pLocate = require('p-locate'); + +const fsStat = promisify(fs.stat); +const fsLStat = promisify(fs.lstat); + +const typeMappings = { + directory: 'isDirectory', + file: 'isFile' +}; + +function checkType({type}) { + if (type in typeMappings) { + return; + } + + throw new Error(`Invalid type specified: ${type}`); +} + +const matchType = (type, stat) => type === undefined || stat[typeMappings[type]](); + +module.exports = async (paths, options) => { + options = { + cwd: process.cwd(), + type: 'file', + allowSymlinks: true, + ...options + }; + checkType(options); + const statFn = options.allowSymlinks ? fsStat : fsLStat; + + return pLocate(paths, async path_ => { + try { + const stat = await statFn(path.resolve(options.cwd, path_)); + return matchType(options.type, stat); + } catch (_) { + return false; + } + }, options); +}; + +module.exports.sync = (paths, options) => { + options = { + cwd: process.cwd(), + allowSymlinks: true, + type: 'file', + ...options + }; + checkType(options); + const statFn = options.allowSymlinks ? fs.statSync : fs.lstatSync; + + for (const path_ of paths) { + try { + const stat = statFn(path.resolve(options.cwd, path_)); + + if (matchType(options.type, stat)) { + return path_; + } + } catch (_) { + } + } +}; diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/license b/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/license new file mode 100644 index 0000000000000..e7af2f77107d7 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/package.json b/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/package.json new file mode 100644 index 0000000000000..063b290253f68 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/package.json @@ -0,0 +1,45 @@ +{ + "name": "locate-path", + "version": "5.0.0", + "description": "Get the first path that exists on disk of multiple paths", + "license": "MIT", + "repository": "sindresorhus/locate-path", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "locate", + "path", + "paths", + "file", + "files", + "exists", + "find", + "finder", + "search", + "searcher", + "array", + "iterable", + "iterator" + ], + "dependencies": { + "p-locate": "^4.1.0" + }, + "devDependencies": { + "ava": "^1.4.1", + "tsd": "^0.7.2", + "xo": "^0.24.0" + } +} diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/readme.md b/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/readme.md new file mode 100644 index 0000000000000..2184c6f30c24c --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path/readme.md @@ -0,0 +1,122 @@ +# locate-path [![Build Status](https://travis-ci.org/sindresorhus/locate-path.svg?branch=master)](https://travis-ci.org/sindresorhus/locate-path) + +> Get the first path that exists on disk of multiple paths + + +## Install + +``` +$ npm install locate-path +``` + + +## Usage + +Here we find the first file that exists on disk, in array order. + +```js +const locatePath = require('locate-path'); + +const files = [ + 'unicorn.png', + 'rainbow.png', // Only this one actually exists on disk + 'pony.png' +]; + +(async () => { + console(await locatePath(files)); + //=> 'rainbow' +})(); +``` + + +## API + +### locatePath(paths, [options]) + +Returns a `Promise` for the first path that exists or `undefined` if none exists. + +#### paths + +Type: `Iterable` + +Paths to check. + +#### options + +Type: `Object` + +##### concurrency + +Type: `number`
+Default: `Infinity`
+Minimum: `1` + +Number of concurrently pending promises. + +##### preserveOrder + +Type: `boolean`
+Default: `true` + +Preserve `paths` order when searching. + +Disable this to improve performance if you don't care about the order. + +##### cwd + +Type: `string`
+Default: `process.cwd()` + +Current working directory. + +##### type + +Type: `string`
+Default: `file`
+Values: `file` `directory` + +The type of paths that can match. + +##### allowSymlinks + +Type: `boolean`
+Default: `true` + +Allow symbolic links to match if they point to the chosen path type. + +### locatePath.sync(paths, [options]) + +Returns the first path that exists or `undefined` if none exists. + +#### paths + +Type: `Iterable` + +Paths to check. + +#### options + +Type: `Object` + +##### cwd + +Same as above. + +##### type + +Same as above. + +##### allowSymlinks + +Same as above. + + +## Related + +- [path-exists](https://github.com/sindresorhus/path-exists) - Check if a path exists + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/index.d.ts b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/index.d.ts new file mode 100644 index 0000000000000..6bbfad4ac7766 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/index.d.ts @@ -0,0 +1,38 @@ +export interface Limit { + /** + @param fn - Promise-returning/async function. + @param arguments - Any arguments to pass through to `fn`. Support for passing arguments on to the `fn` is provided in order to be able to avoid creating unnecessary closures. You probably don't need this optimization unless you're pushing a lot of functions. + @returns The promise returned by calling `fn(...arguments)`. + */ + ( + fn: (...arguments: Arguments) => PromiseLike | ReturnType, + ...arguments: Arguments + ): Promise; + + /** + The number of promises that are currently running. + */ + readonly activeCount: number; + + /** + The number of promises that are waiting to run (i.e. their internal `fn` was not called yet). + */ + readonly pendingCount: number; + + /** + Discard pending promises that are waiting to run. + + This might be useful if you want to teardown the queue at the end of your program's lifecycle or discard any function calls referencing an intermediary state of your app. + + Note: This does not cancel promises that are already running. + */ + clearQueue(): void; +} + +/** +Run multiple promise-returning & async functions with limited concurrency. + +@param concurrency - Concurrency limit. Minimum: `1`. +@returns A `limit` function. +*/ +export default function pLimit(concurrency: number): Limit; diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/index.js b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/index.js new file mode 100644 index 0000000000000..6a72a4c4fc3c7 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/index.js @@ -0,0 +1,57 @@ +'use strict'; +const pTry = require('p-try'); + +const pLimit = concurrency => { + if (!((Number.isInteger(concurrency) || concurrency === Infinity) && concurrency > 0)) { + return Promise.reject(new TypeError('Expected `concurrency` to be a number from 1 and up')); + } + + const queue = []; + let activeCount = 0; + + const next = () => { + activeCount--; + + if (queue.length > 0) { + queue.shift()(); + } + }; + + const run = (fn, resolve, ...args) => { + activeCount++; + + const result = pTry(fn, ...args); + + resolve(result); + + result.then(next, next); + }; + + const enqueue = (fn, resolve, ...args) => { + if (activeCount < concurrency) { + run(fn, resolve, ...args); + } else { + queue.push(run.bind(null, fn, resolve, ...args)); + } + }; + + const generator = (fn, ...args) => new Promise(resolve => enqueue(fn, resolve, ...args)); + Object.defineProperties(generator, { + activeCount: { + get: () => activeCount + }, + pendingCount: { + get: () => queue.length + }, + clearQueue: { + value: () => { + queue.length = 0; + } + } + }); + + return generator; +}; + +module.exports = pLimit; +module.exports.default = pLimit; diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/license b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/license new file mode 100644 index 0000000000000..e7af2f77107d7 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/package.json b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/package.json new file mode 100644 index 0000000000000..99a814f6ecf31 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/package.json @@ -0,0 +1,52 @@ +{ + "name": "p-limit", + "version": "2.3.0", + "description": "Run multiple promise-returning & async functions with limited concurrency", + "license": "MIT", + "repository": "sindresorhus/p-limit", + "funding": "https://github.com/sponsors/sindresorhus", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=6" + }, + "scripts": { + "test": "xo && ava && tsd-check" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "promise", + "limit", + "limited", + "concurrency", + "throttle", + "throat", + "rate", + "batch", + "ratelimit", + "task", + "queue", + "async", + "await", + "promises", + "bluebird" + ], + "dependencies": { + "p-try": "^2.0.0" + }, + "devDependencies": { + "ava": "^1.2.1", + "delay": "^4.1.0", + "in-range": "^1.0.0", + "random-int": "^1.0.0", + "time-span": "^2.0.0", + "tsd-check": "^0.3.0", + "xo": "^0.24.0" + } +} diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/readme.md b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/readme.md new file mode 100644 index 0000000000000..64aa476e2370c --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit/readme.md @@ -0,0 +1,101 @@ +# p-limit [![Build Status](https://travis-ci.org/sindresorhus/p-limit.svg?branch=master)](https://travis-ci.org/sindresorhus/p-limit) + +> Run multiple promise-returning & async functions with limited concurrency + +## Install + +``` +$ npm install p-limit +``` + +## Usage + +```js +const pLimit = require('p-limit'); + +const limit = pLimit(1); + +const input = [ + limit(() => fetchSomething('foo')), + limit(() => fetchSomething('bar')), + limit(() => doSomething()) +]; + +(async () => { + // Only one promise is run at once + const result = await Promise.all(input); + console.log(result); +})(); +``` + +## API + +### pLimit(concurrency) + +Returns a `limit` function. + +#### concurrency + +Type: `number`\ +Minimum: `1`\ +Default: `Infinity` + +Concurrency limit. + +### limit(fn, ...args) + +Returns the promise returned by calling `fn(...args)`. + +#### fn + +Type: `Function` + +Promise-returning/async function. + +#### args + +Any arguments to pass through to `fn`. + +Support for passing arguments on to the `fn` is provided in order to be able to avoid creating unnecessary closures. You probably don't need this optimization unless you're pushing a *lot* of functions. + +### limit.activeCount + +The number of promises that are currently running. + +### limit.pendingCount + +The number of promises that are waiting to run (i.e. their internal `fn` was not called yet). + +### limit.clearQueue() + +Discard pending promises that are waiting to run. + +This might be useful if you want to teardown the queue at the end of your program's lifecycle or discard any function calls referencing an intermediary state of your app. + +Note: This does not cancel promises that are already running. + +## FAQ + +### How is this different from the [`p-queue`](https://github.com/sindresorhus/p-queue) package? + +This package is only about limiting the number of concurrent executions, while `p-queue` is a fully featured queue implementation with lots of different options, introspection, and ability to pause the queue. + +## Related + +- [p-queue](https://github.com/sindresorhus/p-queue) - Promise queue with concurrency control +- [p-throttle](https://github.com/sindresorhus/p-throttle) - Throttle promise-returning & async functions +- [p-debounce](https://github.com/sindresorhus/p-debounce) - Debounce promise-returning & async functions +- [p-all](https://github.com/sindresorhus/p-all) - Run promise-returning & async functions concurrently with optional limited concurrency +- [More…](https://github.com/sindresorhus/promise-fun) + +--- + +
+ + Get professional support for this package with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/index.d.ts b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/index.d.ts new file mode 100644 index 0000000000000..14115e16bacc4 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/index.d.ts @@ -0,0 +1,64 @@ +declare namespace pLocate { + interface Options { + /** + Number of concurrently pending promises returned by `tester`. Minimum: `1`. + + @default Infinity + */ + readonly concurrency?: number; + + /** + Preserve `input` order when searching. + + Disable this to improve performance if you don't care about the order. + + @default true + */ + readonly preserveOrder?: boolean; + } +} + +declare const pLocate: { + /** + Get the first fulfilled promise that satisfies the provided testing function. + + @param input - An iterable of promises/values to test. + @param tester - This function will receive resolved values from `input` and is expected to return a `Promise` or `boolean`. + @returns A `Promise` that is fulfilled when `tester` resolves to `true` or the iterable is done, or rejects if any of the promises reject. The fulfilled value is the current iterable value or `undefined` if `tester` never resolved to `true`. + + @example + ``` + import pathExists = require('path-exists'); + import pLocate = require('p-locate'); + + const files = [ + 'unicorn.png', + 'rainbow.png', // Only this one actually exists on disk + 'pony.png' + ]; + + (async () => { + const foundPath = await pLocate(files, file => pathExists(file)); + + console.log(foundPath); + //=> 'rainbow' + })(); + ``` + */ + ( + input: Iterable | ValueType>, + tester: (element: ValueType) => PromiseLike | boolean, + options?: pLocate.Options + ): Promise; + + // TODO: Remove this for the next major release, refactor the whole definition to: + // declare function pLocate( + // input: Iterable | ValueType>, + // tester: (element: ValueType) => PromiseLike | boolean, + // options?: pLocate.Options + // ): Promise; + // export = pLocate; + default: typeof pLocate; +}; + +export = pLocate; diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/index.js b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/index.js new file mode 100644 index 0000000000000..e13ce1531cac0 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/index.js @@ -0,0 +1,52 @@ +'use strict'; +const pLimit = require('p-limit'); + +class EndError extends Error { + constructor(value) { + super(); + this.value = value; + } +} + +// The input can also be a promise, so we await it +const testElement = async (element, tester) => tester(await element); + +// The input can also be a promise, so we `Promise.all()` them both +const finder = async element => { + const values = await Promise.all(element); + if (values[1] === true) { + throw new EndError(values[0]); + } + + return false; +}; + +const pLocate = async (iterable, tester, options) => { + options = { + concurrency: Infinity, + preserveOrder: true, + ...options + }; + + const limit = pLimit(options.concurrency); + + // Start all the promises concurrently with optional limit + const items = [...iterable].map(element => [element, limit(testElement, element, tester)]); + + // Check the promises either serially or concurrently + const checkLimit = pLimit(options.preserveOrder ? 1 : Infinity); + + try { + await Promise.all(items.map(element => checkLimit(finder, element))); + } catch (error) { + if (error instanceof EndError) { + return error.value; + } + + throw error; + } +}; + +module.exports = pLocate; +// TODO: Remove this for the next major release +module.exports.default = pLocate; diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/license b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/license new file mode 100644 index 0000000000000..e7af2f77107d7 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/package.json b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/package.json new file mode 100644 index 0000000000000..e3de27562508a --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/package.json @@ -0,0 +1,53 @@ +{ + "name": "p-locate", + "version": "4.1.0", + "description": "Get the first fulfilled promise that satisfies the provided testing function", + "license": "MIT", + "repository": "sindresorhus/p-locate", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "promise", + "locate", + "find", + "finder", + "search", + "searcher", + "test", + "array", + "collection", + "iterable", + "iterator", + "race", + "fulfilled", + "fastest", + "async", + "await", + "promises", + "bluebird" + ], + "dependencies": { + "p-limit": "^2.2.0" + }, + "devDependencies": { + "ava": "^1.4.1", + "delay": "^4.1.0", + "in-range": "^1.0.0", + "time-span": "^3.0.0", + "tsd": "^0.7.2", + "xo": "^0.24.0" + } +} diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/readme.md b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/readme.md new file mode 100644 index 0000000000000..f8e2c2eafaac4 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate/readme.md @@ -0,0 +1,90 @@ +# p-locate [![Build Status](https://travis-ci.org/sindresorhus/p-locate.svg?branch=master)](https://travis-ci.org/sindresorhus/p-locate) + +> Get the first fulfilled promise that satisfies the provided testing function + +Think of it like an async version of [`Array#find`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/find). + + +## Install + +``` +$ npm install p-locate +``` + + +## Usage + +Here we find the first file that exists on disk, in array order. + +```js +const pathExists = require('path-exists'); +const pLocate = require('p-locate'); + +const files = [ + 'unicorn.png', + 'rainbow.png', // Only this one actually exists on disk + 'pony.png' +]; + +(async () => { + const foundPath = await pLocate(files, file => pathExists(file)); + + console.log(foundPath); + //=> 'rainbow' +})(); +``` + +*The above is just an example. Use [`locate-path`](https://github.com/sindresorhus/locate-path) if you need this.* + + +## API + +### pLocate(input, tester, [options]) + +Returns a `Promise` that is fulfilled when `tester` resolves to `true` or the iterable is done, or rejects if any of the promises reject. The fulfilled value is the current iterable value or `undefined` if `tester` never resolved to `true`. + +#### input + +Type: `Iterable` + +An iterable of promises/values to test. + +#### tester(element) + +Type: `Function` + +This function will receive resolved values from `input` and is expected to return a `Promise` or `boolean`. + +#### options + +Type: `Object` + +##### concurrency + +Type: `number`
+Default: `Infinity`
+Minimum: `1` + +Number of concurrently pending promises returned by `tester`. + +##### preserveOrder + +Type: `boolean`
+Default: `true` + +Preserve `input` order when searching. + +Disable this to improve performance if you don't care about the order. + + +## Related + +- [p-map](https://github.com/sindresorhus/p-map) - Map over promises concurrently +- [p-filter](https://github.com/sindresorhus/p-filter) - Filter promises concurrently +- [p-any](https://github.com/sindresorhus/p-any) - Wait for any promise to be fulfilled +- [More…](https://github.com/sindresorhus/promise-fun) + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/index.d.ts b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/index.d.ts new file mode 100644 index 0000000000000..2a7319ec2a556 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/index.d.ts @@ -0,0 +1,39 @@ +declare const pTry: { + /** + Start a promise chain. + + @param fn - The function to run to start the promise chain. + @param arguments - Arguments to pass to `fn`. + @returns The value of calling `fn(...arguments)`. If the function throws an error, the returned `Promise` will be rejected with that error. + + @example + ``` + import pTry = require('p-try'); + + (async () => { + try { + const value = await pTry(() => { + return synchronousFunctionThatMightThrow(); + }); + console.log(value); + } catch (error) { + console.error(error); + } + })(); + ``` + */ + ( + fn: (...arguments: ArgumentsType) => PromiseLike | ValueType, + ...arguments: ArgumentsType + ): Promise; + + // TODO: remove this in the next major version, refactor the whole definition to: + // declare function pTry( + // fn: (...arguments: ArgumentsType) => PromiseLike | ValueType, + // ...arguments: ArgumentsType + // ): Promise; + // export = pTry; + default: typeof pTry; +}; + +export = pTry; diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/index.js b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/index.js new file mode 100644 index 0000000000000..db858da29252b --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/index.js @@ -0,0 +1,9 @@ +'use strict'; + +const pTry = (fn, ...arguments_) => new Promise(resolve => { + resolve(fn(...arguments_)); +}); + +module.exports = pTry; +// TODO: remove this in the next major version +module.exports.default = pTry; diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/license b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/license new file mode 100644 index 0000000000000..e7af2f77107d7 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/package.json b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/package.json new file mode 100644 index 0000000000000..81c4d32e40f55 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/package.json @@ -0,0 +1,42 @@ +{ + "name": "p-try", + "version": "2.2.0", + "description": "`Start a promise chain", + "license": "MIT", + "repository": "sindresorhus/p-try", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=6" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "promise", + "try", + "resolve", + "function", + "catch", + "async", + "await", + "promises", + "settled", + "ponyfill", + "polyfill", + "shim", + "bluebird" + ], + "devDependencies": { + "ava": "^1.4.1", + "tsd": "^0.7.1", + "xo": "^0.24.0" + } +} diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/readme.md b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/readme.md new file mode 100644 index 0000000000000..4d7bd64dfcb8b --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/p-try/readme.md @@ -0,0 +1,58 @@ +# p-try [![Build Status](https://travis-ci.org/sindresorhus/p-try.svg?branch=master)](https://travis-ci.org/sindresorhus/p-try) + +> Start a promise chain + +[How is it useful?](http://cryto.net/~joepie91/blog/2016/05/11/what-is-promise-try-and-why-does-it-matter/) + + +## Install + +``` +$ npm install p-try +``` + + +## Usage + +```js +const pTry = require('p-try'); + +(async () => { + try { + const value = await pTry(() => { + return synchronousFunctionThatMightThrow(); + }); + console.log(value); + } catch (error) { + console.error(error); + } +})(); +``` + + +## API + +### pTry(fn, ...arguments) + +Returns a `Promise` resolved with the value of calling `fn(...arguments)`. If the function throws an error, the returned `Promise` will be rejected with that error. + +Support for passing arguments on to the `fn` is provided in order to be able to avoid creating unnecessary closures. You probably don't need this optimization unless you're pushing a *lot* of functions. + +#### fn + +The function to run to start the promise chain. + +#### arguments + +Arguments to pass to `fn`. + + +## Related + +- [p-finally](https://github.com/sindresorhus/p-finally) - `Promise#finally()` ponyfill - Invoked when the promise is settled regardless of outcome +- [More…](https://github.com/sindresorhus/promise-fun) + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/index.d.ts b/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/index.d.ts new file mode 100644 index 0000000000000..54b7ab8f4ec50 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/index.d.ts @@ -0,0 +1,28 @@ +declare const pathExists: { + /** + Check if a path exists. + + @returns Whether the path exists. + + @example + ``` + // foo.ts + import pathExists = require('path-exists'); + + (async () => { + console.log(await pathExists('foo.ts')); + //=> true + })(); + ``` + */ + (path: string): Promise; + + /** + Synchronously check if a path exists. + + @returns Whether the path exists. + */ + sync(path: string): boolean; +}; + +export = pathExists; diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/index.js b/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/index.js new file mode 100644 index 0000000000000..1943921b75850 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/index.js @@ -0,0 +1,23 @@ +'use strict'; +const fs = require('fs'); +const {promisify} = require('util'); + +const pAccess = promisify(fs.access); + +module.exports = async path => { + try { + await pAccess(path); + return true; + } catch (_) { + return false; + } +}; + +module.exports.sync = path => { + try { + fs.accessSync(path); + return true; + } catch (_) { + return false; + } +}; diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/license b/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/license new file mode 100644 index 0000000000000..e7af2f77107d7 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/package.json b/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/package.json new file mode 100644 index 0000000000000..0755256a2b33f --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/package.json @@ -0,0 +1,39 @@ +{ + "name": "path-exists", + "version": "4.0.0", + "description": "Check if a path exists", + "license": "MIT", + "repository": "sindresorhus/path-exists", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "path", + "exists", + "exist", + "file", + "filepath", + "fs", + "filesystem", + "file-system", + "access", + "stat" + ], + "devDependencies": { + "ava": "^1.4.1", + "tsd": "^0.7.2", + "xo": "^0.24.0" + } +} diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/readme.md b/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/readme.md new file mode 100644 index 0000000000000..81f98454567fb --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists/readme.md @@ -0,0 +1,52 @@ +# path-exists [![Build Status](https://travis-ci.org/sindresorhus/path-exists.svg?branch=master)](https://travis-ci.org/sindresorhus/path-exists) + +> Check if a path exists + +NOTE: `fs.existsSync` has been un-deprecated in Node.js since 6.8.0. If you only need to check synchronously, this module is not needed. + +While [`fs.exists()`](https://nodejs.org/api/fs.html#fs_fs_exists_path_callback) is being [deprecated](https://github.com/iojs/io.js/issues/103), there's still a genuine use-case of being able to check if a path exists for other purposes than doing IO with it. + +Never use this before handling a file though: + +> In particular, checking if a file exists before opening it is an anti-pattern that leaves you vulnerable to race conditions: another process may remove the file between the calls to `fs.exists()` and `fs.open()`. Just open the file and handle the error when it's not there. + + +## Install + +``` +$ npm install path-exists +``` + + +## Usage + +```js +// foo.js +const pathExists = require('path-exists'); + +(async () => { + console.log(await pathExists('foo.js')); + //=> true +})(); +``` + + +## API + +### pathExists(path) + +Returns a `Promise` of whether the path exists. + +### pathExists.sync(path) + +Returns a `boolean` of whether the path exists. + + +## Related + +- [path-exists-cli](https://github.com/sindresorhus/path-exists-cli) - CLI for this module + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/index.d.ts b/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/index.d.ts new file mode 100644 index 0000000000000..dd5f5ef615c39 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/index.d.ts @@ -0,0 +1,31 @@ +declare const resolveFrom: { + /** + Resolve the path of a module like [`require.resolve()`](https://nodejs.org/api/globals.html#globals_require_resolve) but from a given path. + + @param fromDirectory - Directory to resolve from. + @param moduleId - What you would use in `require()`. + @returns Resolved module path. Throws when the module can't be found. + + @example + ``` + import resolveFrom = require('resolve-from'); + + // There is a file at `./foo/bar.js` + + resolveFrom('foo', './bar'); + //=> '/Users/sindresorhus/dev/test/foo/bar.js' + ``` + */ + (fromDirectory: string, moduleId: string): string; + + /** + Resolve the path of a module like [`require.resolve()`](https://nodejs.org/api/globals.html#globals_require_resolve) but from a given path. + + @param fromDirectory - Directory to resolve from. + @param moduleId - What you would use in `require()`. + @returns Resolved module path or `undefined` when the module can't be found. + */ + silent(fromDirectory: string, moduleId: string): string | undefined; +}; + +export = resolveFrom; diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/index.js b/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/index.js new file mode 100644 index 0000000000000..44f291c1f0503 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/index.js @@ -0,0 +1,47 @@ +'use strict'; +const path = require('path'); +const Module = require('module'); +const fs = require('fs'); + +const resolveFrom = (fromDirectory, moduleId, silent) => { + if (typeof fromDirectory !== 'string') { + throw new TypeError(`Expected \`fromDir\` to be of type \`string\`, got \`${typeof fromDirectory}\``); + } + + if (typeof moduleId !== 'string') { + throw new TypeError(`Expected \`moduleId\` to be of type \`string\`, got \`${typeof moduleId}\``); + } + + try { + fromDirectory = fs.realpathSync(fromDirectory); + } catch (error) { + if (error.code === 'ENOENT') { + fromDirectory = path.resolve(fromDirectory); + } else if (silent) { + return; + } else { + throw error; + } + } + + const fromFile = path.join(fromDirectory, 'noop.js'); + + const resolveFileName = () => Module._resolveFilename(moduleId, { + id: fromFile, + filename: fromFile, + paths: Module._nodeModulePaths(fromDirectory) + }); + + if (silent) { + try { + return resolveFileName(); + } catch (error) { + return; + } + } + + return resolveFileName(); +}; + +module.exports = (fromDirectory, moduleId) => resolveFrom(fromDirectory, moduleId); +module.exports.silent = (fromDirectory, moduleId) => resolveFrom(fromDirectory, moduleId, true); diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/license b/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/license new file mode 100644 index 0000000000000..e7af2f77107d7 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/package.json b/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/package.json new file mode 100644 index 0000000000000..733df16273dcb --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/package.json @@ -0,0 +1,36 @@ +{ + "name": "resolve-from", + "version": "5.0.0", + "description": "Resolve the path of a module like `require.resolve()` but from a given path", + "license": "MIT", + "repository": "sindresorhus/resolve-from", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "require", + "resolve", + "path", + "module", + "from", + "like", + "import" + ], + "devDependencies": { + "ava": "^1.4.1", + "tsd": "^0.7.2", + "xo": "^0.24.0" + } +} diff --git a/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/readme.md b/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/readme.md new file mode 100644 index 0000000000000..fd4f46f947752 --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from/readme.md @@ -0,0 +1,72 @@ +# resolve-from [![Build Status](https://travis-ci.org/sindresorhus/resolve-from.svg?branch=master)](https://travis-ci.org/sindresorhus/resolve-from) + +> Resolve the path of a module like [`require.resolve()`](https://nodejs.org/api/globals.html#globals_require_resolve) but from a given path + + +## Install + +``` +$ npm install resolve-from +``` + + +## Usage + +```js +const resolveFrom = require('resolve-from'); + +// There is a file at `./foo/bar.js` + +resolveFrom('foo', './bar'); +//=> '/Users/sindresorhus/dev/test/foo/bar.js' +``` + + +## API + +### resolveFrom(fromDirectory, moduleId) + +Like `require()`, throws when the module can't be found. + +### resolveFrom.silent(fromDirectory, moduleId) + +Returns `undefined` instead of throwing when the module can't be found. + +#### fromDirectory + +Type: `string` + +Directory to resolve from. + +#### moduleId + +Type: `string` + +What you would use in `require()`. + + +## Tip + +Create a partial using a bound function if you want to resolve from the same `fromDirectory` multiple times: + +```js +const resolveFromFoo = resolveFrom.bind(null, 'foo'); + +resolveFromFoo('./bar'); +resolveFromFoo('./baz'); +``` + + +## Related + +- [resolve-cwd](https://github.com/sindresorhus/resolve-cwd) - Resolve the path of a module from the current working directory +- [import-from](https://github.com/sindresorhus/import-from) - Import a module from a given path +- [import-cwd](https://github.com/sindresorhus/import-cwd) - Import a module from the current working directory +- [resolve-pkg](https://github.com/sindresorhus/resolve-pkg) - Resolve the path of a package regardless of it having an entry point +- [import-lazy](https://github.com/sindresorhus/import-lazy) - Import a module lazily +- [resolve-global](https://github.com/sindresorhus/resolve-global) - Resolve the path of a globally installed module + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/node_modules/@istanbuljs/load-nyc-config/package.json b/node_modules/@istanbuljs/load-nyc-config/package.json new file mode 100644 index 0000000000000..53207ef348efe --- /dev/null +++ b/node_modules/@istanbuljs/load-nyc-config/package.json @@ -0,0 +1,49 @@ +{ + "name": "@istanbuljs/load-nyc-config", + "version": "1.1.0", + "description": "Utility function to load nyc configuration", + "main": "index.js", + "scripts": { + "pretest": "xo", + "test": "tap", + "snap": "npm test -- --snapshot", + "release": "standard-version" + }, + "engines": { + "node": ">=8" + }, + "license": "ISC", + "repository": { + "type": "git", + "url": "git+https://github.com/istanbuljs/load-nyc-config.git" + }, + "bugs": { + "url": "https://github.com/istanbuljs/load-nyc-config/issues" + }, + "homepage": "https://github.com/istanbuljs/load-nyc-config#readme", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "devDependencies": { + "semver": "^6.3.0", + "standard-version": "^7.0.0", + "tap": "^14.10.5", + "xo": "^0.25.3" + }, + "xo": { + "ignores": [ + "test/fixtures/extends/invalid.*" + ], + "rules": { + "require-atomic-updates": 0, + "capitalized-comments": 0, + "unicorn/import-index": 0, + "import/extensions": 0, + "import/no-useless-path-segments": 0 + } + } +} diff --git a/node_modules/@istanbuljs/schema/CHANGELOG.md b/node_modules/@istanbuljs/schema/CHANGELOG.md new file mode 100644 index 0000000000000..afdc8350f2216 --- /dev/null +++ b/node_modules/@istanbuljs/schema/CHANGELOG.md @@ -0,0 +1,44 @@ +# 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. + +### [0.1.3](https://github.com/istanbuljs/schema/compare/v0.1.2...v0.1.3) (2021-02-13) + + +### Features + +* Add `classPrivateMethods` and `topLevelAwait` default support ([#17](https://github.com/istanbuljs/schema/issues/17)) ([e732889](https://github.com/istanbuljs/schema/commit/e7328894ddeb61da256c1f13c2c2cc2e04f181df)), closes [#16](https://github.com/istanbuljs/schema/issues/16) +* Add `numericSeparator` to default `parserPlugins` ([#12](https://github.com/istanbuljs/schema/issues/12)) ([fe32f00](https://github.com/istanbuljs/schema/commit/fe32f002f54c61467b1c1a487081f51c85ec8d10)), closes [#5](https://github.com/istanbuljs/schema/issues/5) +* Add babel.config.mjs to default exclude ([#10](https://github.com/istanbuljs/schema/issues/10)) ([a4dbeaa](https://github.com/istanbuljs/schema/commit/a4dbeaa7045490a4d46754801ac71f5d99c9bd79)) + + +### Bug Fixes + +* Exclude tests with `tsx` or `jsx` extensions ([#13](https://github.com/istanbuljs/schema/issues/13)) ([c7747f7](https://github.com/istanbuljs/schema/commit/c7747f7a7df8a2b770036834af77dfd0ee445733)), closes [#11](https://github.com/istanbuljs/schema/issues/11) + +### [0.1.2](https://github.com/istanbuljs/schema/compare/v0.1.1...v0.1.2) (2019-12-05) + + +### Features + +* Ignore *.d.ts ([#6](https://github.com/istanbuljs/schema/issues/6)) ([d867eaf](https://github.com/istanbuljs/schema/commit/d867eaff6ca4abcd4301990e2bdcdf53e438e9c4)) +* Update default exclude of dev tool configurations ([#7](https://github.com/istanbuljs/schema/issues/7)) ([c89f818](https://github.com/istanbuljs/schema/commit/c89f8185f30879bcdf8d2f1c3b7aba0ac7056fa9)) + +## [0.1.1](https://github.com/istanbuljs/schema/compare/v0.1.0...v0.1.1) (2019-10-07) + + +### Bug Fixes + +* Add missing `instrument` option ([#3](https://github.com/istanbuljs/schema/issues/3)) ([bf1217d](https://github.com/istanbuljs/schema/commit/bf1217d)) + + +### Features + +* Add `use-spawn-wrap` nyc option ([#4](https://github.com/istanbuljs/schema/issues/4)) ([b2ce2e8](https://github.com/istanbuljs/schema/commit/b2ce2e8)) + +## 0.1.0 (2019-10-05) + + +### Features + +* Initial implementation ([99bd3a5](https://github.com/istanbuljs/schema/commit/99bd3a5)) diff --git a/node_modules/@istanbuljs/schema/LICENSE b/node_modules/@istanbuljs/schema/LICENSE new file mode 100644 index 0000000000000..807a18bdbcb7d --- /dev/null +++ b/node_modules/@istanbuljs/schema/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 CFWare, LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/@istanbuljs/schema/README.md b/node_modules/@istanbuljs/schema/README.md new file mode 100644 index 0000000000000..9cac028823b62 --- /dev/null +++ b/node_modules/@istanbuljs/schema/README.md @@ -0,0 +1,30 @@ +# @istanbuljs/schema + +[![Travis CI][travis-image]][travis-url] +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![MIT][license-image]](LICENSE) + +Schemas describing various structures used by nyc and istanbuljs + +## Usage + +```js +const {nyc} = require('@istanbuljs/schema').defaults; + +console.log(`Default exclude list:\n\t* ${nyc.exclude.join('\n\t* ')}`); +``` + +## `@istanbuljs/schema` for enterprise + +Available as part of the Tidelift Subscription. + +The maintainers of `@istanbuljs/schema` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-istanbuljs-schema?utm_source=npm-istanbuljs-schema&utm_medium=referral&utm_campaign=enterprise) + +[npm-image]: https://img.shields.io/npm/v/@istanbuljs/schema.svg +[npm-url]: https://npmjs.org/package/@istanbuljs/schema +[travis-image]: https://travis-ci.org/istanbuljs/schema.svg?branch=master +[travis-url]: https://travis-ci.org/istanbuljs/schema +[downloads-image]: https://img.shields.io/npm/dm/@istanbuljs/schema.svg +[downloads-url]: https://npmjs.org/package/@istanbuljs/schema +[license-image]: https://img.shields.io/npm/l/@istanbuljs/schema.svg diff --git a/node_modules/@istanbuljs/schema/default-exclude.js b/node_modules/@istanbuljs/schema/default-exclude.js new file mode 100644 index 0000000000000..c6bb526444f7b --- /dev/null +++ b/node_modules/@istanbuljs/schema/default-exclude.js @@ -0,0 +1,22 @@ +'use strict'; + +const defaultExtension = require('./default-extension.js'); +const testFileExtensions = defaultExtension + .map(extension => extension.slice(1)) + .join(','); + +module.exports = [ + 'coverage/**', + 'packages/*/test{,s}/**', + '**/*.d.ts', + 'test{,s}/**', + `test{,-*}.{${testFileExtensions}}`, + `**/*{.,-}test.{${testFileExtensions}}`, + '**/__tests__/**', + + /* Exclude common development tool configuration files */ + '**/{ava,babel,nyc}.config.{js,cjs,mjs}', + '**/jest.config.{js,cjs,mjs,ts}', + '**/{karma,rollup,webpack}.config.js', + '**/.{eslint,mocha}rc.{js,cjs}' +]; diff --git a/node_modules/@istanbuljs/schema/default-extension.js b/node_modules/@istanbuljs/schema/default-extension.js new file mode 100644 index 0000000000000..46ebadca52b38 --- /dev/null +++ b/node_modules/@istanbuljs/schema/default-extension.js @@ -0,0 +1,10 @@ +'use strict'; + +module.exports = [ + '.js', + '.cjs', + '.mjs', + '.ts', + '.tsx', + '.jsx' +]; diff --git a/node_modules/@istanbuljs/schema/index.js b/node_modules/@istanbuljs/schema/index.js new file mode 100644 index 0000000000000..b35f6101a313a --- /dev/null +++ b/node_modules/@istanbuljs/schema/index.js @@ -0,0 +1,466 @@ +'use strict'; + +const defaultExclude = require('./default-exclude.js'); +const defaultExtension = require('./default-extension.js'); + +const nycCommands = { + all: [null, 'check-coverage', 'instrument', 'merge', 'report'], + testExclude: [null, 'instrument', 'report', 'check-coverage'], + instrument: [null, 'instrument'], + checkCoverage: [null, 'report', 'check-coverage'], + report: [null, 'report'], + main: [null], + instrumentOnly: ['instrument'] +}; + +const cwd = { + description: 'working directory used when resolving paths', + type: 'string', + get default() { + return process.cwd(); + }, + nycCommands: nycCommands.all +}; + +const nycrcPath = { + description: 'specify an explicit path to find nyc configuration', + nycCommands: nycCommands.all +}; + +const tempDir = { + description: 'directory to output raw coverage information to', + type: 'string', + default: './.nyc_output', + nycAlias: 't', + nycHiddenAlias: 'temp-directory', + nycCommands: [null, 'check-coverage', 'merge', 'report'] +}; + +const testExclude = { + exclude: { + description: 'a list of specific files and directories that should be excluded from coverage, glob patterns are supported', + type: 'array', + items: { + type: 'string' + }, + default: defaultExclude, + nycCommands: nycCommands.testExclude, + nycAlias: 'x' + }, + excludeNodeModules: { + description: 'whether or not to exclude all node_module folders (i.e. **/node_modules/**) by default', + type: 'boolean', + default: true, + nycCommands: nycCommands.testExclude + }, + include: { + description: 'a list of specific files that should be covered, glob patterns are supported', + type: 'array', + items: { + type: 'string' + }, + default: [], + nycCommands: nycCommands.testExclude, + nycAlias: 'n' + }, + extension: { + description: 'a list of extensions that nyc should handle in addition to .js', + type: 'array', + items: { + type: 'string' + }, + default: defaultExtension, + nycCommands: nycCommands.testExclude, + nycAlias: 'e' + } +}; + +const instrumentVisitor = { + coverageVariable: { + description: 'variable to store coverage', + type: 'string', + default: '__coverage__', + nycCommands: nycCommands.instrument + }, + coverageGlobalScope: { + description: 'scope to store the coverage variable', + type: 'string', + default: 'this', + nycCommands: nycCommands.instrument + }, + coverageGlobalScopeFunc: { + description: 'avoid potentially replaced `Function` when finding global scope', + type: 'boolean', + default: true, + nycCommands: nycCommands.instrument + }, + ignoreClassMethods: { + description: 'class method names to ignore for coverage', + type: 'array', + items: { + type: 'string' + }, + default: [], + nycCommands: nycCommands.instrument + } +}; + +const instrumentParseGen = { + autoWrap: { + description: 'allow `return` statements outside of functions', + type: 'boolean', + default: true, + nycCommands: nycCommands.instrument + }, + esModules: { + description: 'should files be treated as ES Modules', + type: 'boolean', + default: true, + nycCommands: nycCommands.instrument + }, + parserPlugins: { + description: 'babel parser plugins to use when parsing the source', + type: 'array', + items: { + type: 'string' + }, + /* Babel parser plugins are to be enabled when the feature is stage 3 and + * implemented in a released version of node.js. */ + default: [ + 'asyncGenerators', + 'bigInt', + 'classProperties', + 'classPrivateProperties', + 'classPrivateMethods', + 'dynamicImport', + 'importMeta', + 'numericSeparator', + 'objectRestSpread', + 'optionalCatchBinding', + 'topLevelAwait' + ], + nycCommands: nycCommands.instrument + }, + compact: { + description: 'should the output be compacted?', + type: 'boolean', + default: true, + nycCommands: nycCommands.instrument + }, + preserveComments: { + description: 'should comments be preserved in the output?', + type: 'boolean', + default: true, + nycCommands: nycCommands.instrument + }, + produceSourceMap: { + description: 'should source maps be produced?', + type: 'boolean', + default: true, + nycCommands: nycCommands.instrument + } +}; + +const checkCoverage = { + excludeAfterRemap: { + description: 'should exclude logic be performed after the source-map remaps filenames?', + type: 'boolean', + default: true, + nycCommands: nycCommands.checkCoverage + }, + branches: { + description: 'what % of branches must be covered?', + type: 'number', + default: 0, + minimum: 0, + maximum: 100, + nycCommands: nycCommands.checkCoverage + }, + functions: { + description: 'what % of functions must be covered?', + type: 'number', + default: 0, + minimum: 0, + maximum: 100, + nycCommands: nycCommands.checkCoverage + }, + lines: { + description: 'what % of lines must be covered?', + type: 'number', + default: 90, + minimum: 0, + maximum: 100, + nycCommands: nycCommands.checkCoverage + }, + statements: { + description: 'what % of statements must be covered?', + type: 'number', + default: 0, + minimum: 0, + maximum: 100, + nycCommands: nycCommands.checkCoverage + }, + perFile: { + description: 'check thresholds per file', + type: 'boolean', + default: false, + nycCommands: nycCommands.checkCoverage + } +}; + +const report = { + checkCoverage: { + description: 'check whether coverage is within thresholds provided', + type: 'boolean', + default: false, + nycCommands: nycCommands.report + }, + reporter: { + description: 'coverage reporter(s) to use', + type: 'array', + items: { + type: 'string' + }, + default: ['text'], + nycCommands: nycCommands.report, + nycAlias: 'r' + }, + reportDir: { + description: 'directory to output coverage reports in', + type: 'string', + default: 'coverage', + nycCommands: nycCommands.report + }, + showProcessTree: { + description: 'display the tree of spawned processes', + type: 'boolean', + default: false, + nycCommands: nycCommands.report + }, + skipEmpty: { + description: 'don\'t show empty files (no lines of code) in report', + type: 'boolean', + default: false, + nycCommands: nycCommands.report + }, + skipFull: { + description: 'don\'t show files with 100% statement, branch, and function coverage', + type: 'boolean', + default: false, + nycCommands: nycCommands.report + } +}; + +const nycMain = { + silent: { + description: 'don\'t output a report after tests finish running', + type: 'boolean', + default: false, + nycCommands: nycCommands.main, + nycAlias: 's' + }, + all: { + description: 'whether or not to instrument all files of the project (not just the ones touched by your test suite)', + type: 'boolean', + default: false, + nycCommands: nycCommands.main, + nycAlias: 'a' + }, + eager: { + description: 'instantiate the instrumenter at startup (see https://git.io/vMKZ9)', + type: 'boolean', + default: false, + nycCommands: nycCommands.main + }, + cache: { + description: 'cache instrumentation results for improved performance', + type: 'boolean', + default: true, + nycCommands: nycCommands.main, + nycAlias: 'c' + }, + cacheDir: { + description: 'explicitly set location for instrumentation cache', + type: 'string', + nycCommands: nycCommands.main + }, + babelCache: { + description: 'cache babel transpilation results for improved performance', + type: 'boolean', + default: false, + nycCommands: nycCommands.main + }, + useSpawnWrap: { + description: 'use spawn-wrap instead of setting process.env.NODE_OPTIONS', + type: 'boolean', + default: false, + nycCommands: nycCommands.main + }, + hookRequire: { + description: 'should nyc wrap require?', + type: 'boolean', + default: true, + nycCommands: nycCommands.main + }, + hookRunInContext: { + description: 'should nyc wrap vm.runInContext?', + type: 'boolean', + default: false, + nycCommands: nycCommands.main + }, + hookRunInThisContext: { + description: 'should nyc wrap vm.runInThisContext?', + type: 'boolean', + default: false, + nycCommands: nycCommands.main + }, + clean: { + description: 'should the .nyc_output folder be cleaned before executing tests', + type: 'boolean', + default: true, + nycCommands: nycCommands.main + } +}; + +const instrumentOnly = { + inPlace: { + description: 'should nyc run the instrumentation in place?', + type: 'boolean', + default: false, + nycCommands: nycCommands.instrumentOnly + }, + exitOnError: { + description: 'should nyc exit when an instrumentation failure occurs?', + type: 'boolean', + default: false, + nycCommands: nycCommands.instrumentOnly + }, + delete: { + description: 'should the output folder be deleted before instrumenting files?', + type: 'boolean', + default: false, + nycCommands: nycCommands.instrumentOnly + }, + completeCopy: { + description: 'should nyc copy all files from input to output as well as instrumented files?', + type: 'boolean', + default: false, + nycCommands: nycCommands.instrumentOnly + } +}; + +const nyc = { + description: 'nyc configuration options', + type: 'object', + properties: { + cwd, + nycrcPath, + tempDir, + + /* Test Exclude */ + ...testExclude, + + /* Instrumentation settings */ + ...instrumentVisitor, + + /* Instrumentation parser/generator settings */ + ...instrumentParseGen, + sourceMap: { + description: 'should nyc detect and handle source maps?', + type: 'boolean', + default: true, + nycCommands: nycCommands.instrument + }, + require: { + description: 'a list of additional modules that nyc should attempt to require in its subprocess, e.g., @babel/register, @babel/polyfill', + type: 'array', + items: { + type: 'string' + }, + default: [], + nycCommands: nycCommands.instrument, + nycAlias: 'i' + }, + instrument: { + description: 'should nyc handle instrumentation?', + type: 'boolean', + default: true, + nycCommands: nycCommands.instrument + }, + + /* Check coverage */ + ...checkCoverage, + + /* Report options */ + ...report, + + /* Main command options */ + ...nycMain, + + /* Instrument command options */ + ...instrumentOnly + } +}; + +const configs = { + nyc, + testExclude: { + description: 'test-exclude options', + type: 'object', + properties: { + cwd, + ...testExclude + } + }, + babelPluginIstanbul: { + description: 'babel-plugin-istanbul options', + type: 'object', + properties: { + cwd, + ...testExclude, + ...instrumentVisitor + } + }, + instrumentVisitor: { + description: 'instrument visitor options', + type: 'object', + properties: instrumentVisitor + }, + instrumenter: { + description: 'stand-alone instrumenter options', + type: 'object', + properties: { + ...instrumentVisitor, + ...instrumentParseGen + } + } +}; + +function defaultsReducer(defaults, [name, {default: value}]) { + /* Modifying arrays in defaults is safe, does not change schema. */ + if (Array.isArray(value)) { + value = [...value]; + } + + return Object.assign(defaults, {[name]: value}); +} + +module.exports = { + ...configs, + defaults: Object.keys(configs).reduce( + (defaults, id) => { + Object.defineProperty(defaults, id, { + enumerable: true, + get() { + /* This defers `process.cwd()` until defaults are requested. */ + return Object.entries(configs[id].properties) + .filter(([, info]) => 'default' in info) + .reduce(defaultsReducer, {}); + } + }); + + return defaults; + }, + {} + ) +}; diff --git a/node_modules/@istanbuljs/schema/package.json b/node_modules/@istanbuljs/schema/package.json new file mode 100644 index 0000000000000..1d22cde965a63 --- /dev/null +++ b/node_modules/@istanbuljs/schema/package.json @@ -0,0 +1,30 @@ +{ + "name": "@istanbuljs/schema", + "version": "0.1.3", + "description": "Schemas describing various structures used by nyc and istanbuljs", + "main": "index.js", + "scripts": { + "release": "standard-version --sign", + "pretest": "xo", + "test": "tap", + "snap": "npm test -- --snapshot" + }, + "engines": { + "node": ">=8" + }, + "author": "Corey Farrell", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/istanbuljs/schema.git" + }, + "bugs": { + "url": "https://github.com/istanbuljs/schema/issues" + }, + "homepage": "https://github.com/istanbuljs/schema#readme", + "devDependencies": { + "standard-version": "^7.0.0", + "tap": "^14.6.7", + "xo": "^0.25.3" + } +} diff --git a/node_modules/balanced-match/.npmignore b/node_modules/balanced-match/.npmignore deleted file mode 100644 index ae5d8c36ac652..0000000000000 --- a/node_modules/balanced-match/.npmignore +++ /dev/null @@ -1,5 +0,0 @@ -test -.gitignore -.travis.yml -Makefile -example.js diff --git a/node_modules/balanced-match/README.md b/node_modules/balanced-match/README.md index 08e918c0db9a6..d2a48b6b49f2c 100644 --- a/node_modules/balanced-match/README.md +++ b/node_modules/balanced-match/README.md @@ -66,6 +66,12 @@ With [npm](https://npmjs.org) do: npm install balanced-match ``` +## Security contact information + +To report a security vulnerability, please use the +[Tidelift security contact](https://tidelift.com/security). +Tidelift will coordinate the fix and disclosure. + ## License (MIT) diff --git a/node_modules/balanced-match/index.js b/node_modules/balanced-match/index.js index 1685a76293255..c67a64608df7f 100644 --- a/node_modules/balanced-match/index.js +++ b/node_modules/balanced-match/index.js @@ -28,6 +28,9 @@ function range(a, b, str) { var i = ai; if (ai >= 0 && bi > 0) { + if(a===b) { + return [ai, bi]; + } begs = []; left = str.length; diff --git a/node_modules/balanced-match/package.json b/node_modules/balanced-match/package.json index 61349c6edad62..ce6073e0403b5 100644 --- a/node_modules/balanced-match/package.json +++ b/node_modules/balanced-match/package.json @@ -1,7 +1,7 @@ { "name": "balanced-match", "description": "Match balanced character pairs, like \"{\" and \"}\"", - "version": "1.0.0", + "version": "1.0.2", "repository": { "type": "git", "url": "git://github.com/juliangruber/balanced-match.git" @@ -9,10 +9,9 @@ "homepage": "https://github.com/juliangruber/balanced-match", "main": "index.js", "scripts": { - "test": "make test", - "bench": "make bench" + "test": "tape test/test.js", + "bench": "matcha test/bench.js" }, - "dependencies": {}, "devDependencies": { "matcha": "^0.7.0", "tape": "^4.6.0" diff --git a/node_modules/fromentries/LICENSE b/node_modules/fromentries/LICENSE new file mode 100755 index 0000000000000..c7e6852752b72 --- /dev/null +++ b/node_modules/fromentries/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) Feross Aboukhadijeh + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/fromentries/README.md b/node_modules/fromentries/README.md new file mode 100644 index 0000000000000..2e8d9319a83f7 --- /dev/null +++ b/node_modules/fromentries/README.md @@ -0,0 +1,70 @@ +# fromentries [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url] + +[travis-image]: https://img.shields.io/travis/feross/fromentries/master.svg +[travis-url]: https://travis-ci.org/feross/fromentries +[npm-image]: https://img.shields.io/npm/v/fromentries.svg +[npm-url]: https://npmjs.org/package/fromentries +[downloads-image]: https://img.shields.io/npm/dm/fromentries.svg +[downloads-url]: https://npmjs.org/package/fromentries +[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg +[standard-url]: https://standardjs.com + +### Object.fromEntries() ponyfill (in 6 lines) + +## Install + +``` +npm install fromentries +``` + +## Why this package? + +Existing polyfill packages (like +[`object.fromentries`](https://github.com/es-shims/Object.fromEntries)) +pull in a bunch of dependencies and **adds over 8 +KB** to the browser bundle size. This allows them to work in ES3 environments +like IE6, but it's also overkill; almost no one supports IE6 anymore. + +I'd rather not ship tons of extra code to website visitors. A polyfill for this +feature can be implemented in a few short lines of code using modern language +features. That's what `fromentries` (this package) does. + +This means that `fromentries` only works in evergreen browsers like: + +- Chrome +- Firefox +- Edge +- Safari +- Opera + +It does not work in browsers like IE11 and older (unless you transpile it first). + +## Usage + +```js +const fromEntries = require('fromentries') + +const map = new Map([ [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] ]) +const obj = fromEntries(map) +constole.log(obj) // { a: 1, b: 2, c: 3 } + +const searchParams = new URLSearchParams('foo=bar&baz=qux') +const obj2 = fromEntries(searchParams) +console.log(obj2) // { foo: 'bar', 'baz': 'qux' } +``` + +## What is a ponyfill? + +> A *ponyfill* is almost the same as a polyfill, but not quite. Instead of +> patching functionality for older browsers, a ponyfill provides that +> functionality as a standalone module you can use. + +Read more at [PonyFoo](https://ponyfoo.com/articles/polyfills-or-ponyfills). + +## See also + +- [TC39 proposal for Object.fromEntries](https://github.com/tc39/proposal-object-from-entries) + +## License + +MIT. Copyright (c) [Feross Aboukhadijeh](http://feross.org). diff --git a/node_modules/fromentries/index.d.ts b/node_modules/fromentries/index.d.ts new file mode 100644 index 0000000000000..c1c2b612e9898 --- /dev/null +++ b/node_modules/fromentries/index.d.ts @@ -0,0 +1,3 @@ +declare function fromEntries(entries: Iterable): { [k: string]: T }; + +export = fromEntries; diff --git a/node_modules/fromentries/index.js b/node_modules/fromentries/index.js new file mode 100644 index 0000000000000..bd03bf3f86da0 --- /dev/null +++ b/node_modules/fromentries/index.js @@ -0,0 +1,7 @@ +/*! fromentries. MIT License. Feross Aboukhadijeh */ +module.exports = function fromEntries (iterable) { + return [...iterable].reduce((obj, [key, val]) => { + obj[key] = val + return obj + }, {}) +} diff --git a/node_modules/fromentries/package.json b/node_modules/fromentries/package.json new file mode 100644 index 0000000000000..8cca723bf597f --- /dev/null +++ b/node_modules/fromentries/package.json @@ -0,0 +1,58 @@ +{ + "name": "fromentries", + "description": "Object.fromEntries() ponyfill (in 6 lines)", + "version": "1.3.2", + "author": { + "name": "Feross Aboukhadijeh", + "email": "feross@feross.org", + "url": "https://feross.org" + }, + "bugs": { + "url": "https://github.com/feross/fromentries/issues" + }, + "devDependencies": { + "standard": "*", + "tape": "^5.0.1" + }, + "homepage": "https://github.com/feross/fromentries", + "keywords": [ + "Object.fromEntries", + "Object.entries", + "Object.values", + "Object.keys", + "entries", + "values", + "fromEntries", + "ES7", + "ES8", + "shim", + "object", + "keys", + "polyfill", + "ponyfill" + ], + "license": "MIT", + "main": "index.js", + "types": "index.d.ts", + "repository": { + "type": "git", + "url": "git://github.com/feross/fromentries.git" + }, + "scripts": { + "test": "standard && tape test/**/*.js" + }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] +} diff --git a/node_modules/get-package-type/CHANGELOG.md b/node_modules/get-package-type/CHANGELOG.md new file mode 100644 index 0000000000000..5f2c4cc4f4640 --- /dev/null +++ b/node_modules/get-package-type/CHANGELOG.md @@ -0,0 +1,10 @@ +# 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. + +## 0.1.0 (2020-05-19) + + +### Features + +* Initial implementation ([52863f4](https://github.com/cfware/get-package-type/commit/52863f4b2b7b287fe1adcd97331231a2911312dc)) diff --git a/node_modules/get-package-type/LICENSE b/node_modules/get-package-type/LICENSE new file mode 100644 index 0000000000000..971e3b7c2dc83 --- /dev/null +++ b/node_modules/get-package-type/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 CFWare, LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/get-package-type/README.md b/node_modules/get-package-type/README.md new file mode 100644 index 0000000000000..8e1ebf2353d0c --- /dev/null +++ b/node_modules/get-package-type/README.md @@ -0,0 +1,32 @@ +# get-package-type [![NPM Version][npm-image]][npm-url] + +Determine the `package.json#type` which applies to a location. + +## Usage + +```js +const getPackageType = require('get-package-type'); + +(async () => { + console.log(await getPackageType('file.js')); + console.log(getPackageType.sync('file.js')); +})(); +``` + +This function does not validate the value found in `package.json#type`. Any truthy value +found will be returned. Non-truthy values will be reported as `commonjs`. + +The argument must be a filename. +```js +// This never looks at `dir1/`, first attempts to load `./package.json`. +const type1 = await getPackageType('dir1/'); + +// This attempts to load `dir1/package.json`. +const type2 = await getPackageType('dir1/index.cjs'); +``` + +The extension of the filename does not effect the result. The primary use case for this +module is to determine if `myapp.config.js` should be loaded with `require` or `import`. + +[npm-image]: https://img.shields.io/npm/v/get-package-type.svg +[npm-url]: https://npmjs.org/package/get-package-type diff --git a/node_modules/get-package-type/async.cjs b/node_modules/get-package-type/async.cjs new file mode 100644 index 0000000000000..fa7fd5cd1ef33 --- /dev/null +++ b/node_modules/get-package-type/async.cjs @@ -0,0 +1,52 @@ +'use strict'; + +const path = require('path'); +const {promisify} = require('util'); +const readFile = promisify(require('fs').readFile); + +const isNodeModules = require('./is-node-modules.cjs'); +const resultsCache = require('./cache.cjs'); + +const promiseCache = new Map(); + +async function getDirectoryTypeActual(directory) { + if (isNodeModules(directory)) { + return 'commonjs'; + } + + try { + return JSON.parse(await readFile(path.resolve(directory, 'package.json'))).type || 'commonjs'; + } catch (_) { + } + + const parent = path.dirname(directory); + if (parent === directory) { + return 'commonjs'; + } + + return getDirectoryType(parent); +} + +async function getDirectoryType(directory) { + if (resultsCache.has(directory)) { + return resultsCache.get(directory); + } + + if (promiseCache.has(directory)) { + return promiseCache.get(directory); + } + + const promise = getDirectoryTypeActual(directory); + promiseCache.set(directory, promise); + const result = await promise; + resultsCache.set(directory, result); + promiseCache.delete(directory); + + return result; +} + +function getPackageType(filename) { + return getDirectoryType(path.resolve(path.dirname(filename))); +} + +module.exports = getPackageType; diff --git a/node_modules/get-package-type/cache.cjs b/node_modules/get-package-type/cache.cjs new file mode 100644 index 0000000000000..4fd928aa7d804 --- /dev/null +++ b/node_modules/get-package-type/cache.cjs @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = new Map(); diff --git a/node_modules/get-package-type/index.cjs b/node_modules/get-package-type/index.cjs new file mode 100644 index 0000000000000..b5b07348dbe0e --- /dev/null +++ b/node_modules/get-package-type/index.cjs @@ -0,0 +1,7 @@ +'use strict'; + +const getPackageType = require('./async.cjs'); +const getPackageTypeSync = require('./sync.cjs'); + +module.exports = filename => getPackageType(filename); +module.exports.sync = getPackageTypeSync; diff --git a/node_modules/get-package-type/is-node-modules.cjs b/node_modules/get-package-type/is-node-modules.cjs new file mode 100644 index 0000000000000..5a37a7758c322 --- /dev/null +++ b/node_modules/get-package-type/is-node-modules.cjs @@ -0,0 +1,15 @@ +'use strict'; + +const path = require('path'); + +function isNodeModules(directory) { + let basename = path.basename(directory); + /* istanbul ignore next: platform specific branch */ + if (path.sep === '\\') { + basename = basename.toLowerCase(); + } + + return basename === 'node_modules'; +} + +module.exports = isNodeModules; diff --git a/node_modules/get-package-type/package.json b/node_modules/get-package-type/package.json new file mode 100644 index 0000000000000..dcb0ea8e879ae --- /dev/null +++ b/node_modules/get-package-type/package.json @@ -0,0 +1,35 @@ +{ + "name": "get-package-type", + "version": "0.1.0", + "description": "Determine the `package.json#type` which applies to a location", + "type": "module", + "main": "index.cjs", + "exports": "./index.cjs", + "scripts": { + "pretest": "if-ver -ge 10 || exit 0; cfware-lint .", + "tests-only": "nyc -s node test.cjs", + "test": "npm run -s tests-only", + "posttest": "nyc report --check-coverage" + }, + "engines": { + "node": ">=8.0.0" + }, + "author": "Corey Farrell", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/cfware/get-package-type.git" + }, + "bugs": { + "url": "https://github.com/cfware/get-package-type/issues" + }, + "homepage": "https://github.com/cfware/get-package-type#readme", + "dependencies": {}, + "devDependencies": { + "@cfware/lint": "^1.4.3", + "@cfware/nyc": "^0.7.0", + "if-ver": "^1.1.0", + "libtap": "^0.3.0", + "nyc": "^15.0.1" + } +} diff --git a/node_modules/get-package-type/sync.cjs b/node_modules/get-package-type/sync.cjs new file mode 100644 index 0000000000000..85090a6eeaf32 --- /dev/null +++ b/node_modules/get-package-type/sync.cjs @@ -0,0 +1,42 @@ +'use strict'; + +const path = require('path'); +const {readFileSync} = require('fs'); + +const isNodeModules = require('./is-node-modules.cjs'); +const resultsCache = require('./cache.cjs'); + +function getDirectoryTypeActual(directory) { + if (isNodeModules(directory)) { + return 'commonjs'; + } + + try { + return JSON.parse(readFileSync(path.resolve(directory, 'package.json'))).type || 'commonjs'; + } catch (_) { + } + + const parent = path.dirname(directory); + if (parent === directory) { + return 'commonjs'; + } + + return getDirectoryType(parent); +} + +function getDirectoryType(directory) { + if (resultsCache.has(directory)) { + return resultsCache.get(directory); + } + + const result = getDirectoryTypeActual(directory); + resultsCache.set(directory, result); + + return result; +} + +function getPackageTypeSync(filename) { + return getDirectoryType(path.resolve(path.dirname(filename))); +} + +module.exports = getPackageTypeSync; diff --git a/node_modules/is-windows/LICENSE b/node_modules/is-windows/LICENSE new file mode 100644 index 0000000000000..f8de0630598b1 --- /dev/null +++ b/node_modules/is-windows/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-2018, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/is-windows/README.md b/node_modules/is-windows/README.md new file mode 100644 index 0000000000000..485bfdecb37c5 --- /dev/null +++ b/node_modules/is-windows/README.md @@ -0,0 +1,95 @@ +# is-windows [![NPM version](https://img.shields.io/npm/v/is-windows.svg?style=flat)](https://www.npmjs.com/package/is-windows) [![NPM monthly downloads](https://img.shields.io/npm/dm/is-windows.svg?style=flat)](https://npmjs.org/package/is-windows) [![NPM total downloads](https://img.shields.io/npm/dt/is-windows.svg?style=flat)](https://npmjs.org/package/is-windows) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/is-windows.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/is-windows) + +> Returns true if the platform is windows. UMD module, works with node.js, commonjs, browser, AMD, electron, etc. + +Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save is-windows +``` + +## Heads up! + +As of `v0.2.0` this module always returns a function. + +## Node.js usage + +```js +var isWindows = require('is-windows'); + +console.log(isWindows()); +//=> returns true if the platform is windows +``` + +## About + +
+Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +
+ +
+Running Tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +
+ +
+Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +
+ +### Related projects + +You might also be interested in these projects: + +* [is-absolute](https://www.npmjs.com/package/is-absolute): Returns true if a file path is absolute. Does not rely on the path module… [more](https://github.com/jonschlinkert/is-absolute) | [homepage](https://github.com/jonschlinkert/is-absolute "Returns true if a file path is absolute. Does not rely on the path module and can be used as a polyfill for node.js native `path.isAbolute`.") +* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet") +* [is-relative](https://www.npmjs.com/package/is-relative): Returns `true` if the path appears to be relative. | [homepage](https://github.com/jonschlinkert/is-relative "Returns `true` if the path appears to be relative.") +* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject "Returns true if the value is an object and not an array or null.") +* [window-size](https://www.npmjs.com/package/window-size): Reliable way to get the height and width of terminal/console, since it's not calculated or… [more](https://github.com/jonschlinkert/window-size) | [homepage](https://github.com/jonschlinkert/window-size "Reliable way to get the height and width of terminal/console, since it's not calculated or updated the same way on all platforms, environments and node.js versions.") + +### Contributors + +| **Commits** | **Contributor** | +| --- | --- | +| 11 | [jonschlinkert](https://github.com/jonschlinkert) | +| 4 | [doowb](https://github.com/doowb) | +| 1 | [SimenB](https://github.com/SimenB) | +| 1 | [gucong3000](https://github.com/gucong3000) | + +### Author + +**Jon Schlinkert** + +* [linkedin/in/jonschlinkert](https://linkedin.com/in/jonschlinkert) +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) + +### License + +Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on February 14, 2018._ \ No newline at end of file diff --git a/node_modules/is-windows/index.js b/node_modules/is-windows/index.js new file mode 100644 index 0000000000000..55d43e0920b51 --- /dev/null +++ b/node_modules/is-windows/index.js @@ -0,0 +1,27 @@ +/*! + * is-windows + * + * Copyright © 2015-2018, Jon Schlinkert. + * Released under the MIT License. + */ + +(function(factory) { + if (exports && typeof exports === 'object' && typeof module !== 'undefined') { + module.exports = factory(); + } else if (typeof define === 'function' && define.amd) { + define([], factory); + } else if (typeof window !== 'undefined') { + window.isWindows = factory(); + } else if (typeof global !== 'undefined') { + global.isWindows = factory(); + } else if (typeof self !== 'undefined') { + self.isWindows = factory(); + } else { + this.isWindows = factory(); + } +})(function() { + 'use strict'; + return function isWindows() { + return process && (process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE)); + }; +}); diff --git a/node_modules/is-windows/package.json b/node_modules/is-windows/package.json new file mode 100644 index 0000000000000..fca09f9c0d197 --- /dev/null +++ b/node_modules/is-windows/package.json @@ -0,0 +1,71 @@ +{ + "name": "is-windows", + "description": "Returns true if the platform is windows. UMD module, works with node.js, commonjs, browser, AMD, electron, etc.", + "version": "1.0.2", + "homepage": "https://github.com/jonschlinkert/is-windows", + "author": "Jon Schlinkert (https://github.com/jonschlinkert)", + "contributors": [ + "Jon Schlinkert (http://twitter.com/jonschlinkert)", + "Simen Bekkhus (https://github.com/SimenB)", + "刘祺 (gucong.co.cc)" + ], + "repository": "jonschlinkert/is-windows", + "bugs": { + "url": "https://github.com/jonschlinkert/is-windows/issues" + }, + "license": "MIT", + "files": [ + "index.js" + ], + "main": "index.js", + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "mocha" + }, + "devDependencies": { + "gulp-format-md": "^1.0.0", + "mocha": "^3.5.3" + }, + "keywords": [ + "check", + "cywin", + "is", + "is-windows", + "nix", + "operating system", + "os", + "platform", + "process", + "unix", + "win", + "win32", + "windows" + ], + "verb": { + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "related": { + "list": [ + "is-absolute", + "is-glob", + "is-relative", + "isobject", + "window-size" + ] + }, + "lint": { + "reflinks": true + }, + "reflinks": [ + "verb" + ] + } +} diff --git a/node_modules/just-diff/package.json b/node_modules/just-diff/package.json index dbe3aa2ba9cea..00be1d50fddbc 100644 --- a/node_modules/just-diff/package.json +++ b/node_modules/just-diff/package.json @@ -1,8 +1,9 @@ { "name": "just-diff", - "version": "3.0.2", + "version": "3.1.1", "description": "Return an object representing the diffs between two objects. Supports jsonPatch protocol", "main": "index.js", + "types": "index.d.ts", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, @@ -19,4 +20,4 @@ "bugs": { "url": "https://github.com/angus-c/just/issues" } -} +} \ No newline at end of file diff --git a/node_modules/libtap/CHANGELOG.md b/node_modules/libtap/CHANGELOG.md new file mode 100644 index 0000000000000..1606d6dcafa2b --- /dev/null +++ b/node_modules/libtap/CHANGELOG.md @@ -0,0 +1,65 @@ +## 1.0.0 + +### Breaking Changes + +* Run fixture cleanup asynchronously, after teardown +* beforeEach / afterEach no longer received a callback, are assumed to be synchronous + if they do not return a promise +* Improve tap-snapshot folder structure +* Inherit t.saveFixture boolean + +### Features + +* Create fixture symlinks as junctions if pointing at directories +* Add tap-testdir- to the generated test dir folder +* Add `t.mock()` API +* Add `t.before(fn)` API +* Separate `t.match` and `t.has` +* Add `t.notHas()` / `t.notHasStrict()` API's +* Support `t.compareOptions` for configuring tcompare behavior +* Resolve child test promise to results +* Do not report only/grep filtered skips in test.lists +* Make snapshot file location fully customizable + + +## 0.3.0 + +### Breaking Changes + +* Populate `package.json#exports`. This blocks import/require + of 'internal' files +* Convert `options.processDB.spawn` to an async function + in preparation of nyc 15 + +### Features + +* Provide ESM wrapper with named exports using conditional exports + + +## 0.2.0 + +### Breaking Changes + +* Change extension of snapshot files to .cjs + +### Features + +* Add `output` option to `libtap/settings` +* Add `static addAssert` to Test class + + +## 0.1.0 + +This module is based on tap 14.10.2. + +* Node.js 10 is now required +* Assertion synonyms are removed +* Remove stdio-polyfill.js +* Remove browser-process-hrtime +* Remove source-map-support +* Remove mocha DSL +* Remove default stripping of installed modules from stack +* Upgrade tcompare +* Prefer native recursive fs.rmdirSync over rimraf +* Installing rimraf is the users responsibility if it's needed to + support node.js < 12 diff --git a/node_modules/libtap/LICENSE b/node_modules/libtap/LICENSE new file mode 100644 index 0000000000000..19129e315fe59 --- /dev/null +++ b/node_modules/libtap/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/libtap/README.md b/node_modules/libtap/README.md new file mode 100644 index 0000000000000..80b3b895a5f79 --- /dev/null +++ b/node_modules/libtap/README.md @@ -0,0 +1,47 @@ +# libtap + +A TAP test library for +Node.js. + +## `libtap` vs `tap` + +`tap` extends this module and provides many other nice features. Generally +you should be using `require('tap')` instead of `require('libtap')`. In some +edge cases it can be appropriate to use `libtap` directly. + +* Install size is important - `libtap` has significantly less dependencies. +* Your tests are suspectable to transformations or other environmental changes. + `tap` does things that are useful by default, if this causes problems for your + code you may wish to go lower level. + +### Recursive rmdir + +Some parts of `libtap` require recursive rmdir functions. In Node.js 12.10.0+ +this is provided by the Node.js core `fs` module. For older versions of Node.js you +must set compatible functions: + +```js +const rimraf = require('rimraf') +const settings = require('libtap/settings') +settings.rmdirRecursiveSync = dir => rimraf.sync(dir, {glob: false}) +settings.rmdirRecursive = (dir, cb) => rimraf(dir, {glob: false}, cb) +``` + +This is handled by `tap` so only direct users of `libtap` who need to support older +versions of Node.js need to worry about this. + +It is not considered semver-major for a libtap function to use recursive rmdir where +it previously did not. If you test on older versions of Node.js then you must ensure +a user-space implementation is available even if it is not currently needed. + +## Environmental changes still in place + +* signal-exit is run +* async-domain-hook is run +* process.stdout.emit is monkey-patched to swallow EPIPE errors +* process.reallyExit and process.exit are monkey-patched +* Handlers are added to process `beforeexit` and `exit` events + +These all have an effect on the environment and may be undesirable in some edge cases. +Should any/all of these be opt-out or even opt-in? The goal is to be able to create +functional tests using `require('libtap')`. diff --git a/node_modules/libtap/lib/base.js b/node_modules/libtap/lib/base.js new file mode 100644 index 0000000000000..23c121a0704df --- /dev/null +++ b/node_modules/libtap/lib/base.js @@ -0,0 +1,327 @@ +'use strict' + +const assert = require('assert') +const util = require('util') +const {AsyncResource} = require('async_hooks') +const MiniPass = require('minipass') +const Domain = require('async-hook-domain') +const Parser = require('tap-parser') +const ownOr = require('own-or') +const ownOrEnv = require('own-or-env') +const extraFromError = require('./extra-from-error.js') + +class TapWrap extends AsyncResource { + constructor (test) { + super('tap.' + test.constructor.name) + this.test = test + } +} + +class Base extends MiniPass { + constructor (options) { + options = options || {} + super(options) + + this.started = false + + // establish the wrapper resource to limit the domain to this one object + this.hook = new TapWrap(this) + this.hook.runInAsyncScope(() => + this.hookDomain = new Domain((er, type) => { + if (!er || typeof er !== 'object') + er = { error: er } + er.tapCaught = type + this.threw(er) + })) + + this.start = 0 + this.hrtime = null + this.time = null + this.timer = null + this.readyToProcess = false + this.options = options + this.grep = ownOr(options, 'grep', []) + this.grepInvert = ownOr(options, 'grepInvert', false) + this.parent = ownOr(options, 'parent', null) + this.bail = ownOrEnv(options, 'bail', 'TAP_BAIL', true) + this.saveFixture = ownOrEnv(options, 'saveFixture', 'TAP_SAVE_FIXTURE', true) + const name = (ownOr(options, 'name', '') || '').replace(/[\n\r\s\t]/g, ' ') + Object.defineProperty(this, 'name', { + value: name, + writable: false, + enumerable: true, + configurable: false, + }) + this.indent = ownOr(options, 'indent', '') + this.silent = !!options.silent + this.buffered = !!options.buffered || !!options.silent + this.finished = false + this.strict = ownOrEnv(options, 'strict', 'TAP_STRICT', true) + this.omitVersion = !!options.omitVersion + this.preserveWhitespace = ownOr(options, 'preserveWhitespace', true) + this.jobs = +ownOrEnv(options, 'jobs', 'TAP_JOBS') || 0 + this.runOnly = ownOrEnv(options, 'runOnly', 'TAP_ONLY', true) + this.setupParser(options) + this.finished = false + this.output = '' + this.results = null + this.bailedOut = false + this.childId = +ownOrEnv(options, 'childId', 'TAP_CHILD_ID') + || /* istanbul ignore next */ 0 + const skip = ownOr(options, 'skip', false) + const todo = ownOr(options, 'todo', false) + if (skip || todo) + this.main = Base.prototype.main + + this.counts = { + total: 0, + pass: 0, + fail: 0, + skip: 0, + todo: 0, + } + + const ctx = ownOr(options, 'context', null) + delete options.context + this.context = typeof ctx === 'object' || ctx instanceof Object + ? Object.create(ctx) : ctx + + this.lists = { + fail: [], + todo: [], + skip: [], + } + + const doDebug = typeof options.debug === 'boolean' ? options.debug + : /\btap\b/i.test(process.env.NODE_DEBUG || '') + + if (doDebug) + this.debug = debug(this.name) + } + + passing () { + return this.parser.ok + } + + setTimeout (n) { + if (!this.hrtime) + this.hrtime = process.hrtime() + + if (!this.start) + this.start = Date.now() + + if (!n) { + clearTimeout(this.timer) + this.timer = null + } else { + if (this.timer) + clearTimeout(this.timer) + + this.timer = setTimeout(() => this.timeout(), n) + this.timer.duration = n + this.timer.unref() + } + } + + threw (er, extra, proxy) { + this.hook.emitDestroy() + this.hookDomain.destroy() + if (!er || typeof er !== 'object') + er = { error: er } + if (this.name && !proxy) + er.test = this.name + + const message = er.message + + if (!extra) + extra = extraFromError(er, extra, this.options) + + if (this.results) { + this.results.ok = false + if (this.parent) + this.parent.threw(er, extra, true) + else if (!er.stack) + console.error(er) + else { + if (message) + er.message = message + delete extra.stack + delete extra.at + console.error('%s: %s', er.name || 'Error', message) + console.error(er.stack.split(/\n/).slice(1).join('\n')) + console.error(extra) + } + } else + this.parser.ok = false + + return extra + } + + timeout (options) { + this.setTimeout(false) + options = options || {} + options.expired = options.expired || this.name + this.emit('timeout', this.threw(new Error('timeout!'), options)) + } + + runMain (cb) { + this.started = true + this.hook.runInAsyncScope(this.main, this, cb) + } + + main (cb) { + cb() + } + + online (line) { + this.debug('LINE %j', line) + return this.write(this.indent + line) + } + + write (c, e) { + assert.equal(typeof c, 'string') + assert.equal(c.substr(-1), '\n') + + if (this.buffered) { + this.output += c + return true + } + + return super.write(c, e) + } + + onbail (reason) { + this.bailedOut = reason || true + this.emit('bailout', reason) + } + + oncomplete (results) { + if (this.hrtime) { + this.hrtime = process.hrtime(this.hrtime) + this.time = results.time || + Math.round(this.hrtime[0] * 1e6 + this.hrtime[1] / 1e3) / 1e3 + } + + this.debug('ONCOMPLETE %j %j', this.name, results) + + if (this.results) + Object.keys(this.results) + .forEach(k => results[k] = this.results[k]) + + this.results = results + this.emit('complete', results) + const failures = results.failures + .filter(f => f.tapError) + .map(f => { + delete f.diag + delete f.ok + return f + }) + + if (failures.length) + this.options.failures = failures + + this.onbeforeend() + // if we're piping, and buffered, then it means we need to hold off + // on emitting 'end' and calling ondone() until the pipes clear out. + if (this.pipes.length && this.buffer.length) + super.end() + else + this.emit('end') + } + + onbeforeend () {} + ondone () {} + + emit (ev, data) { + if (ev === 'end') { + const ret = super.emit(ev, data) + this.ondone() + this.hook.emitDestroy() + this.hookDomain.destroy() + return ret + } else + return super.emit(ev, data) + } + + setupParser (options) { + this.parser = options.parser || new Parser({ + bail: this.bail, + strict: this.strict, + omitVersion: this.omitVersion, + preserveWhitespace: this.preserveWhitespace, + name: this.name, + }) + this.parser.on('line', l => this.online(l)) + this.parser.once('bailout', reason => this.onbail(reason)) + this.parser.on('complete', result => this.oncomplete(result)) + + this.parser.on('result', () => this.counts.total++) + this.parser.on('pass', () => this.counts.pass++) + this.parser.on('todo', res => { + this.counts.todo++ + this.lists.todo.push(res) + }) + this.parser.on('skip', res => { + // it is uselessly noisy to print out lists of tests skipped + // because of a --grep or --only argument. + if (/^filter: (only|\/.*\/)$/.test(res.skip)) + return + + this.counts.skip++ + this.lists.skip.push(res) + }) + this.parser.on('fail', res => { + this.counts.fail++ + this.lists.fail.push(res) + }) + } + + [util.inspect.custom] () { + return this.constructor.name + ' ' + util.inspect({ + name: this.name, + time: this.time, + hrtime: this.hrtime, + jobs: this.jobs, + buffered: this.buffered, + occupied: this.occupied, + pool: this.pool, + queue: this.queue, + subtests: this.subtests, + output: this.output, + skip: ownOr(this.options, 'skip', false), + todo: ownOr(this.options, 'todo', false), + only: ownOr(this.options, 'only', false), + results: this.results, + options: [ + 'autoend', + 'command', + 'args', + 'stdio', + 'env', + 'cwd', + 'exitCode', + 'signal', + 'expired', + 'timeout', + 'at', + 'skip', + 'todo', + 'only', + 'runOnly' + ].filter(k => this.options[k] !== undefined) + .reduce((s, k) => (s[k] = this.options[k], s), {}) + }) + } + + debug () {} + +} + +const debug = name => (...args) => { + const prefix = `TAP ${process.pid} ${name}: ` + const msg = util.format(...args).trim() + console.error(prefix + msg.split('\n').join(`\n${prefix}`)) +} + +module.exports = Base diff --git a/node_modules/libtap/lib/clean-yaml-object.js b/node_modules/libtap/lib/clean-yaml-object.js new file mode 100644 index 0000000000000..f40bb59628177 --- /dev/null +++ b/node_modules/libtap/lib/clean-yaml-object.js @@ -0,0 +1,130 @@ +'use strict' +const path = require('path') +const fs = require('fs') +const diff = require('diff') +const {format, strict} = require('tcompare') +const stack = require('./stack.js') +const settings = require('../settings') + +const hasOwn = (obj, key) => + Object.prototype.hasOwnProperty.call(obj, key) + +const cleanDiag = object => { + const res = { ...object } + if (hasOwn(res, 'stack') && !hasOwn(res, 'at')) + res.at = stack.parseLine(res.stack.split('\n')[0]) + + const file = res.at && res.at.file && path.resolve(res.at.file) + if (!settings.atTap && file && file.includes(__dirname)) { + // don't print locations in tap itself, that's almost never useful + delete res.at + } + + if (file && res.at && res.at.file && res.at.line && !res.source) { + const content = (() => { + try { + return fs.readFileSync(file, 'utf8') + } catch { + } + })() + if (content) { + const lines = content.split('\n') + if (res.at.line <= lines.length) { + const startLine = Math.max(res.at.line - 2, 0) + const endLine = Math.min(res.at.line + 2, lines.length) + const caret = res.at.column && + res.at.column <= lines[res.at.line - 1].length + ? [new Array(res.at.column).join('-') + '^'] : [] + const context = lines.slice(startLine, res.at.line).concat(caret) + .concat(lines.slice(res.at.line, endLine)) + const csplit = context.join('\n').trimRight() + if (csplit) + res.source = csplit + '\n' + } + } + } + + // show a line by line string diff + // diff the yaml, to make it more humane, especially + // when strings or buffers are very large or multi-line + if (res.found && res.wanted && res.found !== res.wanted && !res.diff) { + const f = res.found + const w = res.wanted + if (typeof f === 'string' && typeof w === 'string') + res.diff = diff.createTwoFilesPatch('expected', 'actual', w + '\n', f + '\n') + .replace(/^=+\n/, '') + else if (f && w && typeof f === 'object' && typeof w === 'object') { + const s = strict(f, w) + if (!s.match) + res.diff = s.diff + else + res.note = 'object identities differ' + } else { + // some mixed stringly bits + // XXX tcompare needs better string diffs + const ff = format(f) + const fw = format(w) + const fs = (typeof f === 'string' ? f : ff) + '\n' + const ws = (typeof w === 'string' ? w : fw) + '\n' + /* istanbul ignore else - impossible without bug in tcompare */ + if (fw !== ff) + res.diff = diff.createTwoFilesPatch('expected', 'actual', ws, fs) + .replace(/^=+\n/, '') + else + res.note = 'object identities differ' + } + if (res.diff === '--- expected\n+++ actual\n') + delete res.diff + if (res.diff) { + delete res.found + delete res.wanted + } + } + + for (const [key, value] of Object.entries(res)) { + if (key === 'todo' || + key === 'time' || + /^_?tapChild/.test(key) || + key === 'childId' || + /^tapStream/.test(key) || + /^tapMochaTest/.test(key) || + key === 'cb' || + key === 'name' || + key === 'indent' || + key === 'skip' || + key === 'bail' || + key === 'grep' || + key === 'grepInvert' || + key === 'only' || + key === 'diagnostic' || + key === 'buffered' || + key === 'parent' || + key === 'domainEmitter' || + key === 'domainThrew' || + key === 'domain' || + // only show saveFixture if it's different from the env + // if env is 1 and value false, or 0 and value=true, print it + key === 'saveFixture' && + value === (process.env.TAP_SAVE_FIXTURE === '1') || + key === 'at' && !value || + key === 'stack' && !value || + key === 'compareOptions' && isEmpty(value)) + delete res[key] + } + + return res +} + +// return true if object is empty, including inherited properties +const isEmpty = obj => { + if (!obj || typeof obj !== 'object') + return true + + for (const key in obj) { + return false + } + + return true +} + +module.exports = cleanDiag diff --git a/node_modules/libtap/lib/diags.js b/node_modules/libtap/lib/diags.js new file mode 100644 index 0000000000000..b77417b279195 --- /dev/null +++ b/node_modules/libtap/lib/diags.js @@ -0,0 +1,5 @@ +'use strict' + +const objToYaml = require('./obj-to-yaml.js') + +module.exports = extra => (y => y ? '\n' + y : '')(objToYaml(extra)) diff --git a/node_modules/libtap/lib/extra-from-error.js b/node_modules/libtap/lib/extra-from-error.js new file mode 100644 index 0000000000000..7440fa5003b1d --- /dev/null +++ b/node_modules/libtap/lib/extra-from-error.js @@ -0,0 +1,81 @@ +'use strict' +const stack = require('./stack.js') + +module.exports = (er, extra, options) => { + // the yaml module puts big stuff here, pluck it off + if (er.source && typeof er.source === 'object' && er.source.context) + er.source = { ...er.source, context: null } + + extra = Object.keys(options || {}).reduce((set, k) => { + if (!(k in set) && !/^tapChild/.test(k)) + set[k] = options[k] + return set + }, extra || {}) + + if (!er || typeof er !== 'object') { + extra.error = er + return extra + } + + const message = er.message ? er.message + : er.stack ? er.stack.split('\n')[0] + : '' + + if (er.message) { + try { + Object.defineProperty(er, 'message', { + value: '', + configurable: true + }) + } catch {} + } + + const st = er.stack && er.stack.substr( + er._babel ? (message + er.codeFrame).length : 0) + if (st) { + const splitst = st.split('\n') + if (er._babel && er.loc) { + const msplit = message.split(': ') + const f = msplit[0].trim() + extra.message = msplit.slice(1).join(': ') + .replace(/ \([0-9]+:[0-9]+\)$/, '').trim() + const file = f.indexOf(process.cwd()) === 0 + ? f.substr(process.cwd().length + 1) : f + if (file !== 'unknown') + delete er.codeFrame + extra.at = { + file, + line: er.loc.line, + column: er.loc.column + 1, + } + } else { + // parse out the 'at' bit from the first line. + extra.at = stack.parseLine(splitst[1]) + } + extra.stack = stack.clean(splitst) + } + + if (message) { + try { + Object.defineProperty(er, 'message', { + value: message, + configurable: true + }) + } catch {} + } + + if (er.name && er.name !== 'Error') + extra.type = er.name + + Object.keys(er).forEach(k => { + if (k === 'message' || + k === 'domainEmitter' || + k === 'domainThrown' || + k === 'domain' || + k === 'domainBound') + return + extra[k] = er[k] + }) + + return extra +} diff --git a/node_modules/libtap/lib/find-main-script.js b/node_modules/libtap/lib/find-main-script.js new file mode 100644 index 0000000000000..8aeef33fb2577 --- /dev/null +++ b/node_modules/libtap/lib/find-main-script.js @@ -0,0 +1,12 @@ +'use strict'; + +// Node.js should provide an API for this +function mainScript(defaultName) { + if (typeof repl !== 'undefined' || '_eval' in process) { + return defaultName + } + + return process.argv[1] || defaultName +} + +module.exports = mainScript; diff --git a/node_modules/libtap/lib/fixture.js b/node_modules/libtap/lib/fixture.js new file mode 100644 index 0000000000000..0c045e63efa24 --- /dev/null +++ b/node_modules/libtap/lib/fixture.js @@ -0,0 +1,80 @@ +const {writeFileSync, linkSync, statSync, symlinkSync} = require('fs') +const {mkdirRecursiveSync} = require('../settings') +const {resolve, dirname} = require('path') + +class Fixture { + constructor (type, content) { + this.type = type + this.content = content + switch (type) { + case 'dir': + if (!content || typeof content !== 'object') + throw new TypeError('dir fixture must have object content') + break + case 'file': + if (typeof content !== 'string' && !Buffer.isBuffer(content)) + throw new TypeError('file fixture must have string/buffer content') + break + case 'link': + case 'symlink': + if (typeof content !== 'string') + throw new TypeError(type + ' fixture must have string target') + break + default: + throw new Error('invalid fixture type: ' + type) + } + } + + get [Symbol.toStringTag] () { + return 'Fixture<' + this.type + '>' + } + + // have to gather up symlinks for the end + static make (abs, f, symlinks = null) { + if (typeof f === 'string' || Buffer.isBuffer(f)) + f = new Fixture('file', f) + else if (f && typeof f === 'object' && !(f instanceof Fixture)) + f = new Fixture('dir', f) + else if (!(f instanceof Fixture)) + throw new Error('invalid fixture type: ' + f) + + const isRoot = symlinks === null + symlinks = symlinks || {} + + switch (f.type) { + case 'symlink': + // have to gather up symlinks for the end, because windows + symlinks[abs] = f.content + break + case 'link': + linkSync(resolve(dirname(abs), f.content), abs) + break + case 'dir': + mkdirRecursiveSync(abs) + for (const [name, fixture] of Object.entries(f.content)) + Fixture.make(`${abs}/${name}`, fixture, symlinks) + break + case 'file': + writeFileSync(abs, f.content) + break + } + + // create all those symlinks we were asked for + if (isRoot) { + for (const [abs, target] of Object.entries(symlinks)) { + symlinkSync(target, abs, isDir(abs, target) ? 'junction' : 'file') + } + } + } +} + +// check if a symlink target is a directory +const isDir = (abs, target) => { + try { + return statSync(resolve(dirname(abs), target)).isDirectory() + } catch (er) { + return false + } +} + +module.exports = Fixture diff --git a/node_modules/libtap/lib/mock.js b/node_modules/libtap/lib/mock.js new file mode 100644 index 0000000000000..d0c39a7544883 --- /dev/null +++ b/node_modules/libtap/lib/mock.js @@ -0,0 +1,84 @@ +const Module = require('module') +const { isAbsolute } = require('path') + +const isPlainObject = obj => obj + && typeof obj === 'object' + && (Object.getPrototypeOf(obj) === null + || Object.getPrototypeOf(obj) === Object.prototype) + +class Mock { + constructor(parentFilename, filename, mocks = {}) { + this.filename = filename + this.mocks = new Map() + + if (!parentFilename || typeof parentFilename !== 'string') { + throw new TypeError('A parentFilename is required to resolve Mocks paths') + } + + if (!filename || typeof filename !== 'string') { + throw new TypeError('t.mock() first argument should be a string') + } + + if (!isPlainObject(mocks)) { + throw new TypeError( + 'mocks should be a a key/value object in which keys ' + + `are the same used in ${filename} require calls` + ) + } + + const self = this + const callerTestRef = Module._cache[parentFilename] + const filePath = Module._resolveFilename(filename, callerTestRef) + + // populate mocks Map from resolved filenames + for (const key of Object.keys(mocks)) { + const mockFilePath = Module._resolveFilename(key, callerTestRef) + this.mocks.set(mockFilePath, mocks[key]) + } + + // keep a cache system for non-mocked files + const seen = new Map() + + class MockedModule extends Module { + require (id) { + const requiredFilePath = Module._resolveFilename(id, this) + + // if it's a mocked file, just serve that instead + if (self.mocks.has(requiredFilePath)) + return self.mocks.get(requiredFilePath) + + // builtin, not-mocked modules need to be loaded via regular require fn + const isWindows = process.platform === 'win32'; + /* istanbul ignore next - platform dependent code path */ + const isRelative = id.startsWith('./') || + id.startsWith('../') || + ((isWindows && id.startsWith('.\\')) || + id.startsWith('..\\')) + if (!isRelative && !isAbsolute(id)) + return super.require(id) + + // if non-mocked file that we've seen, return that instead + // this enable cicle-required deps to work + if (seen.has(requiredFilePath)) + return seen.get(requiredFilePath).exports + + // load any not-mocked module via our MockedModule class + // also sets them in our t.mock realm cache to avoid cicles + const unmockedModule = new MockedModule(requiredFilePath, this) + seen.set(requiredFilePath, unmockedModule) + unmockedModule.load(requiredFilePath) + return unmockedModule.exports + } + } + + this.module = new MockedModule(filePath, callerTestRef) + this.module.load(filePath) + } + + static get(parentFilename, filename, mocks) { + const mock = new Mock(parentFilename, filename, mocks) + return mock.module.exports + } +} + +module.exports = Mock diff --git a/node_modules/libtap/lib/obj-to-yaml.js b/node_modules/libtap/lib/obj-to-yaml.js new file mode 100644 index 0000000000000..330f25f3f6224 --- /dev/null +++ b/node_modules/libtap/lib/obj-to-yaml.js @@ -0,0 +1,12 @@ +'use strict' + +const yaml = require('tap-yaml') +const cleanYamlObject = require('./clean-yaml-object.js') + +module.exports = obj => (clean => + (clean && typeof clean === 'object' && Object.keys(clean).length) ? + ' ---\n' + (yaml.stringify(clean).split('\n').map( + l => l.trim() ? ' ' + l : l.trim() + ).join('\n')) + ' ...\n' + : '' +)(cleanYamlObject(obj)) diff --git a/node_modules/libtap/lib/parse-test-args.js b/node_modules/libtap/lib/parse-test-args.js new file mode 100644 index 0000000000000..5b8a6d8791103 --- /dev/null +++ b/node_modules/libtap/lib/parse-test-args.js @@ -0,0 +1,60 @@ +'use strict' +const typeOf = arg => + typeof arg === 'object' ? (arg ? 'object' : 'null') + : typeof arg + +module.exports = (name_, extra_, cb_, defaultName) => { + let name + let extra + let cb + + const args = [name_, extra_, cb_] + + // this only works if it's literally the 4th argument. + // used internally. + defaultName = defaultName || '' + + for (let i = 0; i < 3 && i < args.length; i++) { + const arg = args[i] + const type = typeOf(arg) + if (name === undefined && (type === 'string' || type === 'number')) + name = '' + arg + else if (type === 'object') { + extra = arg + if (name === undefined) + name = null + } else if (type === 'function') { + if (extra === undefined) + extra = {} + if (name === undefined) + name = null + cb = arg + } else if (arg === false) { + // it's handy while developing to put a ! in front of a + // function to temporarily make a test todo + continue + } else if (type !== 'undefined') + throw new TypeError('unknown argument passed to parseTestArgs: ' + type) + } + + if (!extra) + extra = {} + + if (!cb && defaultName !== '/dev/stdin') + extra.todo = extra.todo || true + + if (!name && extra.name) + name = extra.name + + if (!name && cb && cb.name) + name = cb.name + + name = name || defaultName + extra.name = name + extra.cb = cb || todoCb + return extra +} + +const todoCb = () => { + throw new Error('callback called for TODO test') +} diff --git a/node_modules/libtap/lib/point.js b/node_modules/libtap/lib/point.js new file mode 100644 index 0000000000000..ef72a9bd9e43b --- /dev/null +++ b/node_modules/libtap/lib/point.js @@ -0,0 +1,51 @@ +'use strict' +const diags = require('./diags.js') + +class TestPoint { + constructor (ok, message, extra) { + if (typeof ok !== 'boolean') + throw new TypeError('ok must be boolean') + + if (typeof message !== 'string') + throw new TypeError('message must be a string') + + extra = extra || {} + + this.ok = ok ? 'ok ' : 'not ok ' + this.message = tpMessage(message.trim(), extra) + } +} + +const tpMessage = (message, extra) => { + if (message) + message = ' - ' + message + + // replace \r\n with one space, \t with 2, separately + message = message.replace(/[\n\r]/g, ' ').replace(/\t/g, ' ') + + if (extra.skip) { + message += ' # SKIP' + if (typeof extra.skip === 'string') + message += ' ' + extra.skip + } else if (extra.todo) { + message += ' # TODO' + if (typeof extra.todo === 'string') + message += ' ' + extra.todo + } else if (extra.time) + message += ' # time=' + extra.time + 'ms' + + const diagYaml = extra.diagnostic ? diags(extra) : '' + message += diagYaml + + if (extra.tapChildBuffer || extra.tapChildBuffer === '') { + if (!diagYaml) + message += ' ' + message += '{\n' + extra.tapChildBuffer.trimRight() + '\n}\n' + } + + message += '\n' + + return message +} + +module.exports = TestPoint diff --git a/node_modules/libtap/lib/snapshot.js b/node_modules/libtap/lib/snapshot.js new file mode 100644 index 0000000000000..3a98ffa24bcc5 --- /dev/null +++ b/node_modules/libtap/lib/snapshot.js @@ -0,0 +1,95 @@ +'use strict' + +const fs = require('fs') +const path = require('path') +const cwd = process.cwd() +// initialize once so it doesn't get borked if process.argv is changed later +const main = require('./find-main-script.js')('TAP') +const settings = require('../settings.js') + +class Snapshot { + constructor () { + this.indexes = new Map() + // name them .test.cjs so that nyc ignores them + // base on main test filename, with sanitized argv + const args = process.argv.slice(2) + const head = path.relative(cwd, path.resolve(main)) + const tail = args.length === 0 ? '' + : ('-' + args.join(' ').replace(/[^a-zA-Z0-9\._\-]/g, '-')) + this.file = settings.snapshotFile(cwd, head, tail) + + this.snapshot = null + } + + // should only ever call _one_ of read/save + read (message) { + const index = +this.indexes.get(message) || 1 + this.indexes.set(message, index + 1) + try { + // throw before the require() for missing file, because node + // caches module load errors, and we might create it at some point. + if (!fs.statSync(this.file).isFile()) + throw 'not a file' + this.snapshot = this.snapshot || require(this.file) + } catch { + throw new Error( + 'Snapshot file not found: ' + this.file + '\n' + + 'Run with TAP_SNAPSHOT=1 in the environment\n' + + 'to create snapshot files' + ) + } + + const entry = message + ' ' + index + const s = this.snapshot[entry] + if (s === undefined) + throw new Error( + 'Snapshot entry not found: "' + entry + '"\n' + + 'Run with TAP_SNAPSHOT=1 in the environment\n' + + 'to create snapshots' + ) + + return s.replace(/^\n|\n$/g, '') + } + + snap (data, message) { + const index = +this.indexes.get(message) || 1 + this.indexes.set(message, index + 1) + this.snapshot = this.snapshot || {} + this.snapshot[message + ' ' + index] = data + } + + save () { + if (!this.snapshot) { + try { + fs.unlinkSync(this.file) + } catch (error) { + if (error.code !== 'ENOENT') { + throw error + } + } + } else { + const escape = s => s + .replace(/\\/g, '\\\\') + .replace(/\`/g, '\\\`') + .replace(/\$\{/g, '\\${') + + const data = + '/* IMPORTANT\n' + + ' * This snapshot file is auto-generated, but designed for humans.\n' + + ' * It should be checked into source control and tracked carefully.\n' + + ' * Re-generate by setting TAP_SNAPSHOT=1 and running tests.\n' + + ' * Make sure to inspect the output below. Do not ignore changes!\n' + + ' */\n\'use strict\'\n' + ( + Object.keys(this.snapshot).sort().map(s => + `exports[\`${ + escape(s) + }\`] = \`\n${ + escape(this.snapshot[s]) + }\n\`\n`).join('\n')) + settings.mkdirRecursiveSync(path.dirname(this.file)) + fs.writeFileSync(this.file, data, 'utf8') + } + } +} + +module.exports = Snapshot diff --git a/node_modules/libtap/lib/spawn.js b/node_modules/libtap/lib/spawn.js new file mode 100644 index 0000000000000..4baf8a0315230 --- /dev/null +++ b/node_modules/libtap/lib/spawn.js @@ -0,0 +1,165 @@ +'use strict' +const path = require('path') +const cp = require('child_process') +const ownOr = require('own-or') +const Base = require('./base.js') +const cleanYamlObject = require('./clean-yaml-object.js') + +class Spawn extends Base { + constructor (options) { + // figure out the name before calling super() + options = options || {} + const cwd = ownOr(options, 'cwd', process.cwd()) + const command = options.command + if (!command) + throw new TypeError('no command provided') + const args = ownOr(options, 'args', []) + + options.name = options.name || Spawn.procName(cwd, command, args) + + super(options) + + this.command = options.command + + this.args = options.args + // stdout must be a pipe + if (options.stdio) { + if (typeof options.stdio === 'string') + this.stdio = [ options.stdio, 'pipe', options.stdio ] + else + this.stdio = options.stdio.slice(0) + } else + this.stdio = [ 0, 'pipe', 2 ] + + this.stdio[1] = 'pipe' + options.stdio = this.stdio + + if (!options.env) + options.env = process.env + this.env = { + ...(options.env), + TAP_CHILD_ID: options.childId + || options.env.TAP_CHILD_ID + || /* istanbul ignore next */ 0, + TAP: '1', + TAP_BAIL: this.bail ? '1' : '0', + } + // prune off the extraneous bits so we're not logging the world + this.options.env = Object.keys(this.options.env).reduce((env, k) => { + if (process.env[k] !== this.options.env[k]) + env[k] = this.options.env[k] + return env + }, {}) + + this.cwd = cwd + options.cwd = this.cwd + + this.processDB = ownOr(options, 'processDB', null) || { + spawn: async (name, ...rest) => cp.spawn(...rest) + } + delete options.processDB + + this.proc = null + } + + endAll () { + if (this.proc) + this.proc.kill('SIGKILL') + this.parser.abort('test unfinished') + this.callCb() + } + + main (cb) { + this.cb = cb + this.setTimeout(this.options.timeout) + this.parser.on('comment', c => { + const tomatch = c.match(/# timeout=([0-9]+)\n$/) + if (tomatch) + this.setTimeout(+tomatch[1]) + }) + const options = { + ...(this.options), + cwd: this.cwd, + env: this.env, + stdio: this.stdio, + } + Promise.resolve() + .then(async () => { + this.emit('preprocess', options) + const proc = this.proc = + await this.processDB.spawn(this.name, this.command, this.args, options) + + proc.stdout.pipe(this.parser) + proc.on('close', (code, signal) => this.onprocclose(code, signal)) + proc.on('error', er => this.threw(er)) + this.emit('process', proc) + if (this.parent) + this.parent.emit('spawn', this) + }) + .catch(er => { + er.tapCaught = 'spawn' + this.threw(er) + }) + } + + callCb () { + if (this.cb) + this.cb() + this.cb = null + } + + threw (er, extra, proxy) { + extra = Base.prototype.threw.call(this, er, extra, proxy) + extra = cleanYamlObject(extra) + // unhook entirely + this.parser.abort(er.message, extra) + if (this.proc) { + this.proc.stdout.removeAllListeners('data') + this.proc.stdout.removeAllListeners('end') + this.proc.removeAllListeners('close') + this.proc.kill('SIGKILL') + } + this.callCb() + } + + onprocclose (code, signal) { + this.debug('SPAWN close %j %s', code, signal) + this.options.exitCode = code + if (signal) + this.options.signal = signal + + // spawn closing with no tests is treated as a skip. + if (this.results && this.results.plan && this.results.plan.skipAll && !code && !signal) + this.options.skip = this.results.plan.skipReason || true + + if (code || signal) { + this.results.ok = false + this.parser.ok = false + } + return this.callCb() + } + + timeout (extra) { + if (this.proc) { + this.proc.kill('SIGTERM') + const t = setTimeout(() => { + if (!this.options.signal && this.options.exitCode === undefined) { + Base.prototype.timeout.call(this, extra) + this.proc.kill('SIGKILL') + } + }, 1000) + t.unref() + } + } +} + +Spawn.procName = (cwd, command, args) => ( + (command === process.execPath) + ? path.basename(process.execPath) + ' ' + args.map(a => + a.indexOf(cwd) === 0 ? + './' + a.substr(cwd.length + 1).replace(/\\/g, '/') + : a).join(' ').trim() + : command + ' ' + args.join(' ') +).replace(/\\/g, '/') + +module.exports = Spawn diff --git a/node_modules/libtap/lib/stack.js b/node_modules/libtap/lib/stack.js new file mode 100644 index 0000000000000..21c8e1ae8f510 --- /dev/null +++ b/node_modules/libtap/lib/stack.js @@ -0,0 +1,4 @@ +'use strict' +const {StackUtils, stackUtils} = require('../settings.js') + +module.exports = new StackUtils(stackUtils) diff --git a/node_modules/libtap/lib/stdin.js b/node_modules/libtap/lib/stdin.js new file mode 100644 index 0000000000000..93643f2390df9 --- /dev/null +++ b/node_modules/libtap/lib/stdin.js @@ -0,0 +1,37 @@ +'use strict' +const ownOr = require('own-or') +const Base = require('./base.js') + +class Stdin extends Base { + constructor (options) { + options = options || {} + options.name = ownOr(options, 'name', '/dev/stdin') + super(options) + + // This has to be here for node 0.10's wonky streams + this.stream = ownOr(options, 'tapStream', process.stdin) + this.stream.pause() + } + + main (cb) { + this.stream.on('error', er => { + er.tapCaught = 'stdinError' + this.threw(er) + }) + this.setTimeout(this.options.timeout) + this.stream.pipe(this.parser) + if (this.parent) + this.parent.emit('stdin', this) + this.stream.resume() + this.once('end', cb) + } + + threw (er, extra, proxy) { + extra = super.threw(er, extra, proxy) + this.options = extra + this.parser.abort(er.message, extra) + this.parser.end() + } +} + +module.exports = Stdin diff --git a/node_modules/libtap/lib/tap.js b/node_modules/libtap/lib/tap.js new file mode 100644 index 0000000000000..863ec3c3addf8 --- /dev/null +++ b/node_modules/libtap/lib/tap.js @@ -0,0 +1,247 @@ +'use strict' +const Domain = require('async-hook-domain') +const onExit = require('signal-exit') +const Test = require('./test.js') +const Stdin = require('./stdin.js') +const Spawn = require('./spawn.js') +const objToYaml = require('./obj-to-yaml.js') +const settings = require('../settings.js') + +const _didPipe = Symbol('_didPipe') +const _unmagicPipe = Symbol('_unmagicPipe') + +let processPatched = false +/* eslint-disable-next-line no-unused-vars -- created for side-effects */ +const rootDomain = new Domain((er, type) => { + if (!processPatched) + throw er + else { + if (!er || typeof er !== 'object') + er = { error: er } + er.tapCaught = type + tap.threw(er) + } +}) + +/* istanbul ignore next */ +if (!settings.output) { + // Set exitCode in case process.stderr is also invalid + process.exitCode = 1 + console.error('Output stream is invalid') + process.exit(1) +} + +const monkeypatchEpipe = () => { + const emit = settings.output.emit + settings.output.emit = function (ev, er = {}) { + if (ev !== 'error' || er.code !== 'EPIPE') + return emit.apply(settings.output, arguments) + } +} + +const monkeypatchExit = () => { + const exit = process.exit + const reallyExit = process.reallyExit + + // ensure that we always get run, even if a user does + // process.on('exit', process.exit) + process.reallyExit = code => reallyExit.call(process, onExitEvent(code)) + process.exit = code => exit.call(process, onExitEvent(code)) + process.on('beforeExit', onExitEvent) + process.on('exit', onExitEvent) +} + +class TAP extends Test { + constructor (options) { + super(options) + this.runOnly = process.env.TAP_ONLY === '1' + this.childId = +process.env.TAP_CHILD_ID + || /* istanbul ignore next */ 0 + this.start = Date.now() + this[_didPipe] = false + } + + resume () { + this[_unmagicPipe]() + const ret = this.resume.apply(this, arguments) + this.process() + return ret + } + + [_unmagicPipe] () { + this[_didPipe] = true + this.setTimeout(this.options.timeout) + this.pipe = Test.prototype.pipe + this.write = Test.prototype.write + this.resume = Test.prototype.resume + } + + setTimeout (n, quiet) { + if (n && typeof n === 'number' && !quiet) + this.write(`# timeout=${n}\n`) + return super.setTimeout(n) + } + + pipe () { + this[_unmagicPipe]() + const ret = this.pipe.apply(this, arguments) + this.process() + return ret + } + + write (c, e) { + // this resets write and pipe to standard values + this.patchProcess() + this.pipe(settings.output) + return super.write(c, e) + } + + patchProcess () { + if (processPatched) + return + processPatched = true + monkeypatchEpipe() + monkeypatchExit() + } + + onbeforeend () { + if (this[_didPipe] && this.time && !this.bailedOut) + this.emit('data', '# time=' + this.time + 'ms\n') + } + + ondone () { + return this.emitSubTeardown(this) + } + + // Root test runner doesn't have the 'teardown' event, because it + // isn't hooked into any parent Test as a harness. + teardown (fn) { + if (this.options.autoend !== false) + this.autoend(true) + return super.teardown(fn) + } +} + +let didOnExitEvent = false +const onExitEvent = code => { + if (didOnExitEvent) + return process.exitCode + + didOnExitEvent = true + + if (!tap.results) + tap.endAll() + + if (tap.results && !tap.results.ok && code === 0) + process.exitCode = 1 + + return process.exitCode || code || 0 +} + + +const opt = { name: 'TAP' } +if (process.env.TAP_DEBUG === '1' || + /\btap\b/.test(process.env.NODE_DEBUG || '')) + opt.debug = true + +if (process.env.TAP_GREP) { + opt.grep = process.env.TAP_GREP.split('\n').map(g => { + const p = g.match(/^\/(.*)\/([a-z]*)$/) + g = p ? p[1] : g + const flags = p ? p[2] : '' + return new RegExp(g, flags) + }) +} + +if (process.env.TAP_GREP_INVERT === '1') + opt.grepInvert = true + +if (process.env.TAP_ONLY === '1') + opt.only = true + +const tap = new TAP(opt) + +module.exports = tap.default = tap.t = tap + +tap.Test = Test +tap.Spawn = Spawn +tap.Stdin = Stdin + +// SIGTERM means being forcibly killed, almost always by timeout +let didTimeoutKill = false +onExit((code, signal) => { + if (signal !== 'SIGTERM' || !tap[_didPipe] || didTimeoutKill) + return + + const handles = process._getActiveHandles().filter(h => + h !== settings.output && + h !== process.stdout && + h !== process.stdin && + h !== process.stderr + ) + const requests = process._getActiveRequests() + + const extra = { + at: null, + signal: signal + } + if (requests.length) { + extra.requests = requests.map(r => { + const ret = {} + ret.type = r.constructor.name + + // most everything in node has a context these days + /* istanbul ignore else */ + if (r.context) + ret.context = r.context + + return ret + }) + } + + // Newer node versions don't have this as reliably. + /* istanbul ignore next */ + if (handles.length) { + extra.handles = handles.map(h => { + const ret = {} + ret.type = h.constructor.name + + // all of this is very internal-ish + /* istanbul ignore next */ + if (h.msecs) + ret.msecs = h.msecs + + /* istanbul ignore next */ + if (h._events) + ret.events = Object.keys(h._events) + + /* istanbul ignore next */ + if (h._sockname) + ret.sockname = h._sockname + + /* istanbul ignore next */ + if (h._connectionKey) + ret.connectionKey = h._connectionKey + + return ret + }) + } + + // this is impossible to cover, because it happens after nyc has + // already done its stuff. + /* istanbul ignore else */ + if (!tap.results && tap.timeout) + tap.timeout(extra) + else { + console.error('possible timeout: SIGTERM received after tap end') + if (extra.handles || extra.requests) { + delete extra.signal + if (!extra.at) { + delete extra.at + } + console.error(objToYaml(extra)) + } + didTimeoutKill = true + process.kill(process.pid, 'SIGTERM') + } +}) diff --git a/node_modules/libtap/lib/tap.mjs b/node_modules/libtap/lib/tap.mjs new file mode 100644 index 0000000000000..ed24e7b55e6dc --- /dev/null +++ b/node_modules/libtap/lib/tap.mjs @@ -0,0 +1,31 @@ +import tap from './tap.js' + +export const { + Test, Spawn, Stdin, + spawn, sub, + todo, skip, only, test, + stdinOnly, stdin, + bailout, + comment, + timeout, + main, + process, + processSubtest, + addAssert, + pragma, + plan, end, + beforeEach, + afterEach, + teardown, + autoend, + pass, fail, ok, notOk, + emits, + error, equal, not, same, notSame, strictSame, strictNotSame, + testdir, fixture, + matchSnapshot, + hasStrict, match, notMatch, type, + expectUncaughtException, throwsArgs, throws, doesNotThrow, + rejects, resolves, resolveMatch, resolveMatchSnapshot +} = tap + +export default tap diff --git a/node_modules/libtap/lib/test.js b/node_modules/libtap/lib/test.js new file mode 100644 index 0000000000000..5bd59a40efd3b --- /dev/null +++ b/node_modules/libtap/lib/test.js @@ -0,0 +1,1698 @@ +'use strict' +// We need TWO queues (work and subtest) and one jobs pool +// +// The pool stores buffered subtests being run in parallel. +// +// When new subtests are created, they get put in the work queue and also +// in the subtests queue if they are buffered and jobs>0. When we put a +// test in the subtest queue, we also process it. +// +// Processing the subtest queue means moving tests into the jobs pool until +// the jobs pool length is at this.jobs +// +// Any output functions get put in the work queue if its length > 0 (ie, +// no cutting the line) +// +// Processing the work queue means walking until we run out of things, or +// encounter an unfinished test. When we encounter ANY kind of test, we +// block until its output is completed, dumping it all into the parser. + +const path = require('path') +const assert = require('assert') +const util = require('util') + +const {format, same, strict, match, has, hasStrict} = require('tcompare') +const Deferred = require('trivial-deferred') +const loop = require('function-loop') +const Pool = require('yapool') +const ownOr = require('own-or') +const ownOrEnv = require('own-or-env') +const bindObj = require('bind-obj-methods') + +const Base = require('./base.js') +const Spawn = require('./spawn.js') +const Stdin = require('./stdin.js') +const TestPoint = require('./point.js') +const parseTestArgs = require('./parse-test-args.js') +const Fixture = require('./fixture.js') +const Mock = require('./mock.js') +const cleanYamlObject = require('./clean-yaml-object.js') +const extraFromError = require('./extra-from-error.js') +const stack = require('./stack.js') +const settings = require('../settings.js') +const Snapshot = require('./snapshot.js') +const Waiter = require('./waiter.js') +const findMainScript = require('./find-main-script.js') + +const formatSnapshotDefault = obj => format(obj, { sort: true }) +const cwd = process.cwd() + +// A sigil object for implicit end() calls that should not +// trigger an error if the user then calls t.end() +const IMPLICIT = Symbol('implicit t.end()') + +// Sigil to put in the queue to signal the end of all things +const EOF = Symbol('EOF') + +const _currentAssert = Symbol('_currentAssert') +const _end = Symbol('_end') +const _snapshot = Symbol('_snapshot') +const _getSnapshot = Symbol('_getSnapshot') +const _beforeEnd = Symbol('_beforeEnd') +const _emits = Symbol('_emits') +const _nextChildId = Symbol('_nextChildId') +const _expectUncaught = Symbol('_expectUncaught') +const _createdFixture = Symbol('_createdFixture') +const _beforeCalled = Symbol('_beforeCalled') +const _printedResult = Symbol('_printedResult') + +const hasOwn = (obj, key) => + Object.prototype.hasOwnProperty.call(obj, key) + +const isRegExp = re => + Object.prototype.toString.call(re) === '[object RegExp]' + +const normalizeMessageExtra = (defaultMessage, message, extra) => { + if (message && typeof message === 'object') { + return [defaultMessage, message] + } + + return [ + message || defaultMessage, + extra || {} + ] + +} + +class Test extends Base { + constructor (options) { + options = options || {} + super(options) + + const cmp = ownOr(options, 'compareOptions', undefined) + this.compareOptions = cmp && typeof cmp === 'object' + ? Object.create(cmp) : {} + + this[_nextChildId] = 1 + this.pushedEnd = false + this.jobs = ownOr(options, 'jobs', 1) + + this.doingStdinOnly = false + this.onTeardown = [] + this[_createdFixture] = false + this.subtests = [] + this.pool = new Pool() + this.queue = ['TAP version 13\n'] + + // snapshots are keyed off of the main file that loads the + // root test object. Typically, this is the TAP object. + // To do this, we climb the ladder and only save in the teardown + // of that root (parentless) test object. This allows handling + // cases where the same test name can be used multiple times + // in a single test file, which would otherwise clobber snapshots. + this.writeSnapshot = ownOrEnv( + options, 'snapshot', 'TAP_SNAPSHOT', true) + + if (this.parent && this.parent.cleanSnapshot) + this.cleanSnapshot = this.parent.cleanSnapshot + + this.formatSnapshot = this.parent && this.parent.formatSnapshot + + this.noparallel = false + if (options.cb) + this.cb = (...args) => this.hook.runInAsyncScope(options.cb, this, ...args) + + this.occupied = false + this[_currentAssert] = null + this[_beforeEnd] = [] + this.count = 0 + this.n = 0 + this.ended = false + this.explicitEnded = false + this.multiEndThrew = false + this.assertAt = null + this.assertStack = null + this.planEnd = -1 + this.onBeforeEach = [] + this.onAfterEach = [] + this.ranAfterEach = false + + this[_expectUncaught] = [] + + // bind all methods to this object, so we can pass t.end as a callback + // and do `const test = require('tap').test` like people do. + const bound = Object.create(null) + bindObj(this, this, bound) + bindObj(this, Object.getPrototypeOf(this), bound) + bindObj(this, Test.prototype, bound) + } + + spawn (cmd, args, options, name) { + if (typeof args === 'string') + args = [ args ] + + args = args || [] + + if (typeof options === 'string') { + name = options + options = {} + } + + options = options || {} + options.name = ownOr(options, 'name', name) + options.command = cmd + options.args = args + + return this.sub(Spawn, options, Test.prototype.spawn) + } + + sub (Class, extra, caller) { + if (this.bailedOut) + return + + if (this.doingStdinOnly) + throw new Error('cannot run subtests in stdinOnly mode') + + if (this.results || this.ended) { + const er = new Error('cannot create subtest after parent test end') + Error.captureStackTrace(er, caller) + this.threw(er) + return Promise.resolve(this) + } + + extra.childId = this[_nextChildId]++ + + if (!extra.skip && this.grep.length) { + const m = this.grep[0].test(extra.name) + const match = this.grepInvert ? !m : m + if (!match) { + const p = 'filter' + (this.grepInvert ? ' out' : '') + ': ' + extra.skip = p + this.grep[0] + } + } + + if (extra.only && !this.runOnly) + this.comment('%j has `only` set but all tests run', extra.name) + + if (this.runOnly && !extra.only) + extra.skip = 'filter: only' + + if (extra.todo || extra.skip) { + this.pass(extra.name, extra) + return Promise.resolve(this) + } + + if (!extra.grep) { + extra.grep = this.grep.slice(1) + extra.grepInvert = this.grepInvert + } + + extra.indent = ' ' + if (this.jobs > 1 && process.env.TAP_BUFFER === undefined) + extra.buffered = ownOr(extra, 'buffered', true) + else + extra.buffered = ownOrEnv(extra, 'buffered', 'TAP_BUFFER', true) + + extra.bail = ownOr(extra, 'bail', this.bail) + extra.saveFixture = ownOr(extra, 'saveFixture', this.saveFixture) + extra.parent = this + extra.stack = stack.captureString(80, caller) + extra.context = this.context + extra.compareOptions = this.compareOptions + const t = new Class(extra) + + this.queue.push(t) + this.subtests.push(t) + this.emit('subtestAdd', t) + + const d = new Deferred() + t.deferred = d + this.process() + return d.promise + } + + todo (name, extra, cb) { + extra = parseTestArgs(name, extra, cb) + extra.todo = extra.todo || true + return this.sub(Test, extra, Test.prototype.todo) + } + + skip (name, extra, cb) { + extra = parseTestArgs(name, extra, cb) + extra.skip = extra.skip || true + return this.sub(Test, extra, Test.prototype.skip) + } + + only (name, extra, cb) { + extra = parseTestArgs(name, extra, cb) + extra.only = true + return this.sub(Test, extra, Test.prototype.only) + } + + test (name, extra, cb) { + extra = parseTestArgs(name, extra, cb) + return this.sub(Test, extra, Test.prototype.test) + } + + stdinOnly (extra) { + const stream = extra && extra.tapStream || process.stdin + if (this.queue.length !== 1 || + this.queue[0] !== 'TAP version 13\n' || + this.processing || + this.results || + this.occupied || + this.pool.length || + this.subtests.length) + throw new Error('Cannot use stdinOnly on a test in progress') + + this.doingStdinOnly = true + this.queue.length = 0 + this.parser.on('child', p => { + // pretend to be a rooted parser, so it gets counts. + p.root = p + const t = new Base({ + name: p.name, + parent: this, + parser: p, + root: p, + bail: p.bail, + strict: p.strict, + omitVersion: p.omitVersion, + preserveWhitespace: p.preserveWhitespace, + childId: this[_nextChildId]++, + }) + this.emit('subtestAdd', t) + this.emit('subtestStart', t) + this.emit('subtestProcess', t) + p.on('complete', () => { + t.time = p.time + this.emit('subtestEnd', t) + }) + }) + stream.pause() + stream.pipe(this.parser) + stream.resume() + } + + stdin (name, extra) { + extra = parseTestArgs(name, extra, false, '/dev/stdin') + return this.sub(Stdin, extra, Test.prototype.stdin) + } + + bailout (message) { + if (this.parent && (this.results || this.ended)) + this.parent.bailout(message) + else { + this.process() + message = message ? ' ' + ('' + message).trim() : '' + message = message.replace(/[\r\n]/g, ' ') + this.parser.write('Bail out!' + message + '\n') + } + this.end(IMPLICIT) + this.process() + } + + comment (...args) { + const body = util.format(...args) + const message = '# ' + body.split(/\r?\n/).join('\n# ') + '\n' + + if (this.results) + this.write(message) + else + this.queue.push(message) + this.process() + } + + timeout (options) { + options = options || {} + options.expired = options.expired || this.name + if (this.occupied && this.occupied.timeout) + this.occupied.timeout(options) + else + Base.prototype.timeout.call(this, options) + this.end(IMPLICIT) + } + + main (cb) { + this.setTimeout(this.options.timeout) + this.debug('MAIN pre', this) + + const end = () => { + this.debug(' > implicit end for promise') + this.end(IMPLICIT) + done() + } + + const done = (er) => { + if (er) + this.threw(er) + + if (this.results || this.bailedOut) + cb() + else + this.ondone = cb + } + + // This bit of overly clever line-noise wraps the call to user-code + // in a try-catch. We can't rely on the domain for this yet, because + // the 'end' event can trigger a throw after the domain is unhooked, + // but before this is no longer the official "active test" + const ret = (() => { + try { + return this.cb(this) + } catch (er) { + if (!er || typeof er !== 'object') + er = { error: er } + er.tapCaught = 'testFunctionThrow' + this.threw(er) + } + })() + + if (ret && ret.then) { + this.promise = ret + ret.tapAbortPromise = done + ret.then(end, er => { + if (!er || typeof er !== 'object') + er = { error: er } + er.tapCaught = 'returnedPromiseRejection' + done(er) + }) + } else + done() + + this.debug('MAIN post', this) + } + + process () { + if (this.processing) + return this.debug(' < already processing') + + this.debug('\nPROCESSING(%s)', this.name, this.queue.length) + this.processing = true + + while (!this.occupied) { + const p = this.queue.shift() + if (!p) + break + if (p instanceof Base) { + this.processSubtest(p) + } else if (p === EOF) { + this.debug(' > EOF', this.name) + // I AM BECOME EOF, DESTROYER OF STREAMS + if (this.writeSnapshot) + this[_getSnapshot]().save() + this.parser.end() + } else if (p instanceof TestPoint) { + this.debug(' > TESTPOINT') + this.parser.write(p.ok + (++this.n) + p.message) + } else if (typeof p === 'string') { + this.debug(' > STRING') + this.parser.write(p) + } else if (p instanceof Waiter) { + p.ready = true + this.occupied = p + p.finish() + } else { + /* istanbul ignore else */ + if (Array.isArray(p)) { + this.debug(' > METHOD') + const m = p.shift() + const ret = this[m].apply(this, p) + if (ret && typeof ret.then === 'function') { + // returned promise + ret.then(() => { + this.processing = false + this.process() + }, er => { + this.processing = false + this.threw(er) + }) + return + } + } else { + throw new Error('weird thing got in the queue') + } + } + } + + while (!this.noparallel && this.pool.length < this.jobs) { + const p = this.subtests.shift() + if (!p) + break + + if (!p.buffered) { + this.noparallel = true + break + } + + this.debug('start subtest', p) + this.emit('subtestStart', p) + this.pool.add(p) + if (this.bailedOut) + this.onbufferedend(p) + else + this.runBeforeEach(p, () => + p.runMain(() => this.onbufferedend(p))) + } + + this.debug('done processing', this.queue, this.occupied) + this.processing = false + + // just in case any tests ended, and we have sync stuff still + // waiting around in the queue to be processed + if (!this.occupied && this.queue.length) + this.process() + + this.maybeAutoend() + } + + processSubtest (p) { + this.debug(' > subtest') + this.occupied = p + if (!p.buffered) { + this.emit('subtestStart', p) + this.debug(' > subtest indented') + p.pipe(this.parser, { end: false }) + this.runBeforeEach(p, () => + this.writeSubComment(p, () => + p.runMain(() => this.onindentedend(p)))) + } else if (p.readyToProcess) { + this.emit('subtestProcess', p) + this.debug(' > subtest buffered, finished') + // finished! do the thing! + this.occupied = null + if (!p.passing() || !p.silent) { + this.queue.unshift(['emitSubTeardown', p]) + this.printResult(p.passing(), p.name, p.options, true) + } + } else { + this.occupied = p + this.debug(' > subtest buffered, unfinished', p) + // unfinished buffered test. + // nothing to do yet, just leave it there. + this.queue.unshift(p) + } + } + + emitSubTeardown (p) { + // if it's not a thing that CAN have teardowns, nothing to do here + if (!p.onTeardown) + return + + const otd = p.onTeardown + p.onTeardown = [] + const threw = er => { + if (!er || typeof er !== 'object') + er = { error: er } + er.tapCaught = 'teardown' + delete p.options.time + p.threw(er) + } + for (let i = 0; i < otd.length; i++) { + const fn = otd[i] + try { + const ret = fn.call(p) + if (ret && typeof ret.then === 'function') { + p.onTeardown = otd.slice(i + 1) + this.queue.unshift(['emitSubTeardown', p]) + return ret.then(() => this.emitSubTeardown(p), er => { + if (!er || typeof er !== 'object') + er = { error: er } + er.tapCaught = 'teardown' + throw er + }) + } + } catch (er) { + threw(er) + } + } + + // ok we're done, just delete the fixture if it created one. + // do this AFTER all user-generated teardowns, and asynchronously so + // that we can do the fancy backoff dance for Win32's weirdo fs. + if (p[_createdFixture]) { + const {rmdirRecursive} = settings + return new Promise((res, rej) => { + rmdirRecursive(p[_createdFixture], er => + er ? /* istanbul ignore next - rimraf never fails lol */ rej(er) + : res()) + }).then(() => p.emit('teardown')) + } else + p.emit('teardown') + } + + writeSubComment (p, cb) { + const comment = '# Subtest' + + (p.name ? ': ' + p.name : '') + + '\n' + this.parser.write(comment) + cb() + } + + onbufferedend (p) { + delete p.ondone + p.results = p.results || {} + p.readyToProcess = true + const to = p.options.timeout + const dur = (to && p.passing()) ? Date.now() - p.start : null + if (dur && dur > to) + p.timeout() + else + p.setTimeout(false) + this.debug('%s.onbufferedend', this.name, p.name, p.results.bailout) + this.pool.remove(p) + p.options.tapChildBuffer = p.output || '' + p.options.stack = '' + if (p.time) + p.options.time = p.time + if (this.occupied === p) + this.occupied = null + p.deferred.resolve(p.results) + this.emit('subtestEnd', p) + this.process() + } + + onindentedend (p) { + this.emit('subtestProcess', p) + delete p.ondone + this.debug('onindentedend', p) + this.noparallel = false + const sti = this.subtests.indexOf(p) + if (sti !== -1) + this.subtests.splice(sti, 1) + p.readyToProcess = true + p.options.time = p.time + const to = p.options.timeout + const dur = (to && p.passing()) ? Date.now() - p.start : null + if (dur && dur > to) + p.timeout() + else + p.setTimeout(false) + this.debug('onindentedend %s(%s)', this.name, p.name) + this.occupied = null + this.debug('OIE(%s) b>shift into queue', this.name, this.queue) + p.options.stack = '' + + this.queue.unshift(['emitSubTeardown', p]) + this.printResult(p.passing(), p.name, p.options, true) + + this.debug('OIE(%s) shifted into queue', this.name, this.queue) + p.deferred.resolve(p.results) + this.emit('subtestEnd', p) + this.process() + } + + addAssert (name, length, fn) { + if (!name) + throw new TypeError('name is required for addAssert') + + if (!(typeof length === 'number' && length >= 0)) + throw new TypeError('number of args required') + + if (typeof fn !== 'function') + throw new TypeError('function required for addAssert') + + if (Test.prototype[name] || this[name]) + throw new TypeError('attempt to re-define `' + name + '` assert') + + const ASSERT = function (...args) { + this.currentAssert = ASSERT + args.splice(length, 0, ...normalizeMessageExtra('', ...args.splice(length, 2))) + + return fn.apply(this, args) + } + this[name] = ASSERT + } + + static addAssert (name, length, fn) { + this.prototype.addAssert(name, length, fn) + } + + printResult (ok, message, extra, front) { + this[_printedResult] = true + + if (this.doingStdinOnly) + throw new Error('cannot print results in stdinOnly mode') + const n = this.count + 1 + this.currentAssert = Test.prototype.printResult + const fn = this[_currentAssert] + this[_currentAssert] = null + + if (this.planEnd !== -1 && n > this.planEnd) { + if (!this.passing()) + return + + const failMessage = this.explicitEnded + ? 'test after end() was called' + : 'test count exceeds plan' + + const er = new Error(failMessage) + Error.captureStackTrace(er, fn) + er.test = this.name + er.plan = this.planEnd + this.threw(er) + return + } + + extra = extra || {} + + if (extra.expectFail) + ok = !ok + + if (this.assertAt) { + extra.at = this.assertAt + this.assertAt = null + } + + if (this.assertStack) { + extra.stack = this.assertStack + this.assertStack = null + } + + if (hasOwn(extra, 'stack') && !hasOwn(extra, 'at')) + extra.at = stack.parseLine(extra.stack.split('\n')[0]) + + if (!ok && !extra.skip && !hasOwn(extra, 'at')) { + assert.equal(typeof fn, 'function') + extra.at = stack.at(fn) + if (!extra.todo) + extra.stack = stack.captureString(80, fn) + } + + const diagnostic = + typeof extra.diagnostic === 'boolean' ? extra.diagnostic + : process.env.TAP_DIAG === '0' ? false + : process.env.TAP_DIAG === '1' ? true + : extra.skip ? false + : !ok + + if (diagnostic) + extra.diagnostic = true + + this.count = n + message = message + '' + const res = { ok, message, extra } + + const output = new TestPoint(ok, message, extra) + // when we jump the queue, skip an extra line + if (front) + output.message = output.message.trimRight() + '\n\n' + + if (this.occupied && this.occupied instanceof Waiter && + this.occupied.finishing) + front = true + + if (front) { + this.emit('result', res) + this.parser.write(output.ok + (++this.n) + output.message) + if (this.bail && !ok && !extra.skip && !extra.todo) + this.parser.write('Bail out! ' + message + '\n') + } else { + this.queue.push(['emit', 'result', res], output) + if (this.bail && !ok && !extra.skip && !extra.todo) + this.queue.push('Bail out! ' + message + '\n') + } + + if (this.planEnd === this.count) + this.end(IMPLICIT) + + this.process() + } + + pragma (set) { + const p = Object.keys(set).reduce((acc, i) => + acc + 'pragma ' + (set[i] ? '+' : '-') + i + '\n', '') + this.queue.push(p) + this.process() + } + + plan (n, comment) { + if (this.bailedOut) + return + + if (this.planEnd !== -1) { + throw new Error('Cannot set plan more than once') + } + + if (typeof n !== 'number' || n < 0) { + throw new TypeError('plan must be a number') + } + + // Cannot get any tests after a trailing plan, or a plan of 0 + const ending = this.count !== 0 || n === 0 + + if (n === 0 && comment && !this.options.skip) + this.options.skip = comment + + this.planEnd = n + comment = comment ? ' # ' + comment.trim() : '' + this.queue.push('1..' + n + comment + '\n') + + if (ending) + this.end(IMPLICIT) + else + this.process() + } + + end (implicit) { + if (this.doingStdinOnly && implicit !== IMPLICIT) + throw new Error('cannot explicitly end while in stdinOnly mode') + this.debug('END implicit=%j', implicit === IMPLICIT) + if (this.ended && implicit === IMPLICIT) + return + + if (this[_beforeEnd].length) { + for (let b = 0; b < this[_beforeEnd].length; b++) { + const m = this[_beforeEnd][b].shift() + this[m].apply(this, this[_beforeEnd][b]) + } + this[_beforeEnd].length = 0 + } + + // beyond here we have to be actually done with things, or else + // the semantic checks on counts and such will be off. + if (!queueEmpty(this) || this.occupied) { + if (!this.pushedEnd) + this.queue.push(['end', implicit]) + this.pushedEnd = true + return this.process() + } + + if (!this.ranAfterEach && this.parent) { + this.ranAfterEach = true + this.parent.runAfterEach(this, () => this[_end](implicit)) + return + } else + this[_end](implicit) + } + + [_end] (implicit) { + this.ended = true + + if (implicit !== IMPLICIT && !this.multiEndThrew) { + if (this.explicitEnded) { + this.multiEndThrew = true + const er = new Error('test end() method called more than once') + Error.captureStackTrace(er, this[_currentAssert] || + Test.prototype[_end]) + er.test = this.name + this.threw(er) + return + } + this.explicitEnded = true + } + + if (this.planEnd === -1) { + this.debug('END(%s) implicit plan', this.name, this.count) + this.plan(this.count) + } + + this.queue.push(EOF) + + if (this[_expectUncaught].length) { + const wanted = this[_expectUncaught] + this[_expectUncaught] = [] + const diag = { + wanted: wanted.map(a => a.filter(e => e != null)), + test: this.name, + at: null, + stack: null, + } + const msg = 'test end without expected uncaught exceptions' + this.queue.push(['threw', Object.assign(new Error(msg), diag)]) + } + this.process() + } + + threw (er, extra, proxy) { + // this can only happen if a beforeEach function raises an error + if (this.parent && !this.started) { + this.cb = () => { + this.threw(er) + this.end() + } + return + } + + if (!er || typeof er !== 'object') + er = { error: er } + + if (this[_expectUncaught].length && er.tapCaught === 'uncaughtException') { + const [wanted, message, extra] = this[_expectUncaught].shift() + const actual = isRegExp(wanted) ? er.message : er + return wanted + ? this.match(actual, wanted, message, extra) + : this.pass(message, extra) + } + + if (this.name && !proxy) + er.test = this.name + if (!proxy) + extra = extraFromError(er, extra, this.options) + Base.prototype.threw.call(this, er, extra, proxy) + + if (!this.results) { + this.fail(extra.message || er.message, extra) + if (!proxy) + this.end(IMPLICIT) + } + // threw while waiting for a promise to resolve. + // probably it's not ever gonna. + if (this.occupied && this.occupied instanceof Waiter) + this.occupied.abort(Object.assign( + new Error('error thrown while awaiting Promise'), + { thrown: er } + )) + + this.process() + } + + runBeforeEach (who, cb) { + if (this.parent) + this.parent.runBeforeEach(who, () => { + loop(who, this.onBeforeEach, cb, er => { + who.threw(er) + cb() + }) + }) + else + loop(who, this.onBeforeEach, cb, er => { + who.threw(er) + cb() + }) + } + + runAfterEach (who, cb) { + loop(who, this.onAfterEach, () => { + if (this.parent) + this.parent.runAfterEach(who, cb) + else + cb() + }, who.threw) + } + + beforeEach (fn) { + // use function so that 'this' can be overridden + this.onBeforeEach.push(function () { + return fn.call(this, this) + }) + } + + afterEach (fn) { + // use function so that 'this' can be overridden + this.onAfterEach.push(function () { + return fn.call(this, this) + }) + } + + teardown (fn) { + this.onTeardown.push(fn) + } + + shouldAutoend () { + const should = ( + this.options.autoend && + !this.ended && + !this.occupied && + queueEmpty(this) && + !this.pool.length && + !this.subtests.length && + this.planEnd === -1 + ) + return should + } + + autoend (value) { + // set to false to NOT trigger autoend + if (value === false) { + this.options.autoend = false + clearTimeout(this.autoendTimer) + } else { + this.options.autoend = true + this.maybeAutoend() + } + } + + maybeAutoend () { + if (this.shouldAutoend()) { + clearTimeout(this.autoendTimer) + this.autoendTimer = setTimeout(() => { + if (this.shouldAutoend()) { + clearTimeout(this.autoendTimer) + this.autoendTimer = setTimeout(() => { + if (this.shouldAutoend()) + this.end(IMPLICIT) + }) + } + }) + } + } + + onbail (message) { + super.onbail(message) + this.end(IMPLICIT) + if (!this.parent) + this.endAll() + } + + endAll (sub) { + // in the case of the root TAP test object, we might sometimes + // call endAll on a bailing-out test, as the process is ending + // In that case, we WILL have a this.occupied and a full queue + // These cases are very rare to encounter in other Test objs tho + this.processing = true + if (this.occupied) { + const p = this.occupied + if (p instanceof Waiter) + p.abort(new Error('test unfinished')) + else if (p.endAll) + p.endAll(true) + else + p.parser.abort('test unfinished') + } else if (sub) { + this.process() + if (queueEmpty(this)) { + const options = Object.assign({}, this.options) + this.options.at = null + this.options.stack = '' + options.test = this.name + this.fail('test unfinished', options) + } + } + + if (this.promise && this.promise.tapAbortPromise) + this.promise.tapAbortPromise() + + if (this.occupied) { + this.queue.unshift(this.occupied) + this.occupied = null + } + + endAllQueue(this.queue) + this.processing = false + this.process() + this.parser.end() + } + + get currentAssert () { + return this[_currentAssert] + } + + set currentAssert (fn) { + if (!this[_currentAssert]) + this[_currentAssert] = fn + } + + pass (message, extra) { + this.currentAssert = Test.prototype.pass + + this.printResult(true, ...normalizeMessageExtra('(unnamed test)', message, extra)) + return true + } + + fail (message, extra) { + [message, extra] = normalizeMessageExtra('(unnamed test)', message, extra) + this.currentAssert = Test.prototype.fail + + this.printResult(false, message, extra) + return !!(extra.todo || extra.skip) + } + + ok (obj, message, extra) { + [message, extra] = normalizeMessageExtra('expect truthy value', message, extra) + this.currentAssert = Test.prototype.ok + + return obj ? this.pass(message, extra) : this.fail(message, extra) + } + + notOk (obj, message, extra) { + [message, extra] = normalizeMessageExtra('expect falsey value', message, extra) + this.currentAssert = Test.prototype.notOk + + return this.ok(!obj, message, extra) + } + + emits (emitter, event, message, extra) { + [message, extra] = normalizeMessageExtra(`expect ${event} event to be emitted`, message, extra) + this.currentAssert = Test.prototype.emits + + const handler = () => handler.emitted = true + handler.emitted = false + emitter.once(event, handler) + extra.at = stack.at(Test.prototype.emits) + extra.stack = stack.captureString(80, Test.prototype.emits) + this[_beforeEnd].push([_emits, emitter, event, handler, message, extra]) + } + + [_emits] (emitter, event, handler, message, extra) { + if (handler.emitted) + return this.pass(message, extra) + else { + emitter.removeListener(event, handler) + return this.fail(message, extra) + } + } + + error (er, message, extra) { + [message, extra] = normalizeMessageExtra('', message, extra) + this.currentAssert = Test.prototype.error + + if (!er) { + return this.pass(message || 'should not error', extra) + } + + if (!(er instanceof Error)) { + extra.found = er + return this.fail(message || 'non-Error error encountered', extra) + } + + message = message || er.message + extra.origin = cleanYamlObject(extraFromError(er)) + extra.found = er + return this.fail(message, extra) + } + + equal (found, wanted, message, extra) { + [message, extra] = normalizeMessageExtra('should be equal', message, extra) + this.currentAssert = Test.prototype.equal + + if (found === wanted) { + return this.pass(message, extra) + } + + const objects = found && + wanted && + typeof found === 'object' && + typeof wanted === 'object' + if (objects) { + const s = strict(found, wanted, this.compareOptions) + if (!s.match) + extra.diff = s.diff + else { + extra.found = found + extra.wanted = wanted + extra.note = 'object identities differ' + } + } else { + extra.found = found + extra.wanted = wanted + } + + extra.compare = '===' + + return this.fail(message, extra) + } + + not (found, wanted, message, extra) { + [message, extra] = normalizeMessageExtra('should not be equal', message, extra) + this.currentAssert = Test.prototype.not + + if (found !== wanted) { + return this.pass(message, extra) + } + + extra.found = found + extra.doNotWant = wanted + extra.compare = '!==' + + return this.fail(message, extra) + } + + same (found, wanted, message, extra) { + [message, extra] = normalizeMessageExtra('should be equivalent', message, extra) + this.currentAssert = Test.prototype.same + + const s = same(found, wanted, this.compareOptions) + if (!s.match) + extra.diff = s.diff + else { + extra.found = found + extra.wanted = wanted + } + return this.ok(s.match, message, extra) + } + + notSame (found, wanted, message, extra) { + [message, extra] = normalizeMessageExtra('should not be equivalent', message, extra) + this.currentAssert = Test.prototype.notSame + + extra.found = found + extra.doNotWant = wanted + const s = same(found, wanted, this.compareOptions) + return this.notOk(s.match, message, extra) + } + + strictSame (found, wanted, message, extra) { + [message, extra] = normalizeMessageExtra('should be equivalent strictly', message, extra) + this.currentAssert = Test.prototype.strictSame + + const s = strict(found, wanted, this.compareOptions) + if (!s.match) + extra.diff = s.diff + else { + extra.found = found + extra.wanted = wanted + } + + return this.ok(s.match, message, extra) + } + + strictNotSame (found, wanted, message, extra) { + [message, extra] = normalizeMessageExtra('should not be equivalent strictly', message, extra) + this.currentAssert = Test.prototype.strictNotSame + + extra.found = found + extra.doNotWant = wanted + const s = strict(found, wanted, this.compareOptions) + return this.notOk(s.match, message, extra) + } + + get fullname () { + const main = process.argv.slice(1).join(' ').trim() + return (this.parent ? this.parent.fullname + : main.indexOf(cwd) === 0 ? main.substr(cwd.length + 1) + : path.basename(main)).replace(/\\/g, '/') + + ' ' + (this.name || '').trim() + } + + get snapshotFile () { + return this[_getSnapshot]().file + } + set snapshotFile (file) { + this[_getSnapshot]().file = file + } + + get testdirName () { + const re = /[^a-zA-Z0-9\._\-]+/ig + if (!this.parent) { + const main = findMainScript('TAP') + // put in a prefix in the dirname so do not inadvertently run it + // on a subsequent tap invocation, if it was saved. + const dir = path.dirname(main) + const base = 'tap-testdir-' + (path.basename(main).replace(/\.[^.]+$/, '') + + ' ' + process.argv.slice(2).join(' ')).trim() + return dir + '/' + base.replace(re, '-') + } + + return this.parent.testdirName + '-' + + (this.name || 'unnamed test').replace(re, '-') + } + + testdir (fixture) { + const {rmdirRecursiveSync} = settings + const dir = this.testdirName + rmdirRecursiveSync(dir) + if (!this.saveFixture) + this[_createdFixture] = dir + Fixture.make(dir, fixture || {}) + return dir + } + + fixture (type, content) { + return new Fixture(type, content) + } + + mock (module, mocks) { + const {file} = stack.at(Test.prototype.mock) + const resolved = path.resolve(file) + return Mock.get(resolved, module, mocks) + } + + matchSnapshot (found, message, extra) { + [message, extra] = normalizeMessageExtra('must match snapshot', message, extra) + this.currentAssert = Test.prototype.matchSnapshot + + // use notOk because snap doesn't return a truthy value + const m = this.fullname + ' > ' + message + if (typeof found !== 'string') { + found = (this.formatSnapshot || formatSnapshotDefault)(found) + if (typeof found !== 'string') + found = formatSnapshotDefault(found) + } + + found = this.cleanSnapshot(found) + + return this.writeSnapshot + ? this.notOk(this[_getSnapshot]().snap(found, m), + message, extra) + : this.equal(found, this[_getSnapshot]().read(m), + message, extra) + } + + [_getSnapshot] () { + if (this[_snapshot]) + return this[_snapshot] + + if (this.parent) { + const parentSnapshot = this.parent[_getSnapshot]() + // very rare for the parent to not have one. + /* istanbul ignore else */ + if (parentSnapshot) + return this[_snapshot] = parentSnapshot + } + + return this[_snapshot] = new Snapshot() + } + + cleanSnapshot (string) { + return string + } + + has (found, wanted, message, extra) { + [message, extra] = normalizeMessageExtra('should contain all provided fields', message, extra) + this.currentAssert = Test.prototype.has + + const s = has(found, wanted, this.compareOptions) + if (!s.match) + extra.diff = s.diff + else { + extra.found = found + extra.pattern = wanted + } + return this.ok(s.match, message, extra) + } + + notHas (found, wanted, message, extra) { + [message, extra] = normalizeMessageExtra('should not contain all provided fields', message, extra) + this.currentAssert = Test.prototype.notHas + + extra.found = found + extra.pattern = wanted + const s = has(found, wanted, this.compareOptions) + return this.notOk(s.match, message, extra) + } + + hasStrict (found, wanted, message, extra) { + [message, extra] = normalizeMessageExtra('should contain all provided fields strictly', message, extra) + this.currentAssert = Test.prototype.hasStrict + + const s = hasStrict(found, wanted, this.compareOptions) + if (!s.match) + extra.diff = s.diff + else { + extra.found = found + extra.pattern = wanted + } + return this.ok(s.match, message, extra) + } + + notHasStrict (found, wanted, message, extra) { + [message, extra] = normalizeMessageExtra('should not contain all provided fields strictly', message, extra) + this.currentAssert = Test.prototype.notHasStrict + + extra.found = found + extra.pattern = wanted + const s = hasStrict(found, wanted, this.compareOptions) + return this.notOk(s.match, message, extra) + } + + match (found, wanted, message, extra) { + [message, extra] = normalizeMessageExtra('should match pattern provided', message, extra) + this.currentAssert = Test.prototype.match + + const s = match(found, wanted, this.compareOptions) + if (!s.match) + extra.diff = s.diff + else + extra.found = found + extra.pattern = wanted + return this.ok(s.match, message, extra) + } + + notMatch (found, wanted, message, extra) { + [message, extra] = normalizeMessageExtra('should not match pattern provided', message, extra) + this.currentAssert = Test.prototype.notMatch + + extra.found = found + extra.pattern = wanted + const s = match(found, wanted, this.compareOptions) + return this.notOk(s.match, message, extra) + } + + type (obj, klass, message, extra) { + this.currentAssert = Test.prototype.type + + const name = typeof klass === 'function' ? + klass.name || '(anonymous constructor)' + : klass; + + [message, extra] = normalizeMessageExtra(`type is ${name}`, message, extra) + + // simplest case, it literally is the same thing + if (obj === klass) { + return this.pass(message, extra) + } + + const tof = typeof obj + const type = (!obj && tof === 'object') ? 'null' + // treat as object, but not Object + // t.type(() => {}, Function) + : (tof === 'function' && + typeof klass === 'function' && + klass !== Object) ? 'object' + : tof + + if (type === 'object' && klass !== 'object') { + if (typeof klass === 'function') { + extra.found = Object.getPrototypeOf(obj).constructor.name + extra.wanted = name + return this.ok(obj instanceof klass, message, extra) + } + + // check prototype chain for name + // at this point, we already know klass is not a function + // if the klass specified is an obj in the proto chain, pass + // if the name specified is the name of a ctor in the chain, pass + for (let p = obj; p; p = Object.getPrototypeOf(p)) { + const ctor = p.constructor && p.constructor.name + if (p === klass || ctor === name) { + return this.pass(message, extra) + } + } + } + + return this.equal(type, name, message, extra) + } + + expectUncaughtException (...args) { + let [, ...rest] = this.throwsArgs('expect uncaughtException', ...args) + this[_expectUncaught].push(rest) + } + + throwsArgs (defaultMessage, ...args) { + let fn, wanted, message, extra + for (let i = 0; i < args.length; i++) { + const arg = args[i] + if (typeof arg === 'function') { + if (arg === Error || arg.prototype instanceof Error) { + wanted = arg + } else if (!fn) { + fn = arg + } + } else if (typeof arg === 'string' && arg) { + message = arg + } else if (typeof arg === 'object') { + if (!wanted) { + wanted = arg + } else { + extra = arg + } + } + } + + [message, extra] = normalizeMessageExtra(defaultMessage, message, extra) + + if (wanted) { + if (wanted instanceof Error) { + const w = { + message: wanted.message + } + if (wanted.name) { + w.name = wanted.name + } + + // intentionally copying non-local properties, since this + // is an Error object, and those are funky. + for (let i in wanted) { + w[i] = wanted[i] + } + wanted = w + + message += ': ' + (wanted.name || 'Error') + ' ' + wanted.message + extra.wanted = wanted + } + } + + return [fn, wanted, message, extra] + } + + throws (...args) { + this.currentAssert = Test.prototype.throws + + const [fn, wanted, message, extra] = + this.throwsArgs('expected to throw', ...args) + + if (typeof fn !== 'function') { + extra.todo = extra.todo || true + return this.pass(message, extra) + } + + try { + fn() + return this.fail(message, extra) + } catch (er) { + // 'name' is a getter. + if (er.name) { + Object.defineProperty(er, 'name', { + value: er.name + '', + enumerable: true, + configurable: true, + writable: true + }) + } + + const actual = isRegExp(wanted) ? er.message : er + return wanted + ? this.match(actual, wanted, message, extra) && er + : this.pass(message, extra) && er + } + } + + doesNotThrow (fn, message, extra) { + [message, extra] = normalizeMessageExtra('', message, extra) + this.currentAssert = Test.prototype.doesNotThrow + + if (typeof fn === 'string') { + const x = fn + fn = message + message = x + } + + if (!message) { + message = fn && fn.name || 'expected to not throw' + } + + if (typeof fn !== 'function') { + extra.todo = extra.todo || true + return this.pass(message, extra) + } + + try { + fn() + return this.pass(message, extra) + } catch (er) { + const e = extraFromError(er, extra) + e.message = er.message + return this.fail(message, e) + } + } + + before (fn) { + this.currentAssert = Test.prototype.before + if (this.occupied || this[_printedResult]) + throw new Error('t.before() called after starting tests') + + if (this[_beforeCalled]) + throw new Error('called t.before() more than once') + + this[_beforeCalled] = true + + // if it throws, we let it kill the test + const ret = fn.call(this) + + if (ret && typeof ret.then === 'function') + this.waitOn(ret, w => { + if (w.rejected) { + // sort of a mini bailout, just for this one test + // drop everything from the queue, quit right away + this.queue.length = 0 + this.threw(w.value) + this.planEnd = -1 + this.count = 1 + this.end() + } + }) + } + + waitOn (promise, cb, expectReject) { + const w = new Waiter(promise, w => { + assert.equal(this.occupied, w) + cb(w) + this.occupied = null + this.process() + }, expectReject) + this.queue.push(w) + this.process() + return w.promise + } + + // like throws, but rejects a returned promise instead + // also, can pass in a promise instead of a function + rejects (...args) { + this.currentAssert = Test.prototype.rejects + + let fn, wanted, extra, promise, message + for (let i = 0; i < args.length; i++) { + const arg = args[i] + if (typeof arg === 'function') { + if (arg === Error || arg.prototype instanceof Error) { + wanted = arg + } else if (!fn) { + fn = arg + } + } else if (typeof arg === 'string' && arg) { + message = arg + } else if (arg && typeof arg.then === 'function' && !promise) { + promise = arg + } else if (typeof arg === 'object') { + if (!wanted) { + wanted = arg + } else { + extra = arg + } + } + } + + if (!extra) + extra = {} + + if (!message) + message = fn && fn.name || 'expect rejected Promise' + + if (wanted) { + if (wanted instanceof Error) { + const w = { + message: wanted.message + } + if (wanted.name) + w.name = wanted.name + + // intentionally copying non-local properties, since this + // is an Error object, and those are funky. + for (let i in wanted) { + w[i] = wanted[i] + } + wanted = w + + message += ': ' + (wanted.name || 'Error') + ' ' + wanted.message + extra.wanted = wanted + } + } + + if (!promise && typeof fn !== 'function') { + extra.todo = extra.todo || true + this.pass(message, extra) + return Promise.resolve(this) + } + + if (!promise) + promise = fn() + + if (!promise || typeof promise.then !== 'function') { + this.fail(message, extra) + return Promise.resolve(this) + } + + extra.at = stack.at(this.currentAssert) + return this.waitOn(promise, w => { + if (!w.rejected) { + extra.found = w.value + return this.fail(message, extra) + } + + const er = w.value + // 'name' is a getter. + if (er && er.name) { + Object.defineProperty(er, 'name', { + value: er.name + '', + enumerable: true, + configurable: true, + writable: true + }) + } + + const actual = isRegExp(wanted) && er ? er.message : er + return wanted ? this.match(actual, wanted, message, extra) + : this.pass(message, extra) + }, true) + } + + resolves (promise, message, extra) { + [message, extra] = normalizeMessageExtra('expect resolving Promise', message, extra) + this.currentAssert = Test.prototype.resolves + + if (typeof promise === 'function') + promise = promise() + + extra.at = stack.at(this.currentAssert) + + if (!promise || typeof promise.then !== 'function') { + this.fail(message, extra) + return Promise.resolve(this) + } + + return this.waitOn(promise, w => { + extra.found = w.value + this.ok(w.resolved, message, extra) + }) + } + + resolveMatch (promise, wanted, message, extra) { + [message, extra] = normalizeMessageExtra('expect resolving Promise', message, extra) + this.currentAssert = Test.prototype.resolveMatch + + extra.at = stack.at(this.currentAssert) + + if (typeof promise === 'function') + promise = promise() + + if (!promise || typeof promise.then !== 'function') { + this.fail(message, extra) + return Promise.resolve(this) + } + + return this.waitOn(promise, w => { + extra.found = w.value + return w.rejected ? this.fail(message, extra) + : this.match(w.value, wanted, message, extra) + }) + } + + resolveMatchSnapshot (promise, message, extra) { + [message, extra] = normalizeMessageExtra('expect resolving Promise', message, extra) + this.currentAssert = Test.prototype.resolveMatch + + extra.at = stack.at(this.currentAssert) + + if (typeof promise === 'function') + promise = promise() + + if (!promise || typeof promise.then !== 'function') { + this.fail(message, extra) + return Promise.resolve(this) + } + + return this.waitOn(promise, w => { + extra.found = w.value + return w.rejected ? this.fail(message, extra) + : this.matchSnapshot(w.value, message, extra) + }) + } +} + +const endAllQueue = queue => { + queue.forEach((p, i) => { + if ((p instanceof Base) && !p.readyToProcess) + queue[i] = new TestPoint(false, + 'child test left in queue:' + + ' t.' + p.constructor.name.toLowerCase() + ' ' + p.name, + p.options) + }) + queue.push(['end', IMPLICIT]) +} + +const queueEmpty = t => + t.queue.length === 0 || + t.queue.length === 1 && t.queue[0] === 'TAP version 13\n' + +module.exports = Test diff --git a/node_modules/libtap/lib/waiter.js b/node_modules/libtap/lib/waiter.js new file mode 100644 index 0000000000000..cf21ce1eb4ec9 --- /dev/null +++ b/node_modules/libtap/lib/waiter.js @@ -0,0 +1,59 @@ +class Waiter { + constructor (promise, cb, expectReject) { + this.cb = cb + this.ready = false + this.value = null + this.resolved = false + this.rejected = false + this.done = false + this.finishing = false + this.expectReject = !!expectReject + this.promise = new Promise(res => this.resolve = res) + promise.then(value => { + if (this.done) { + return + } + + this.resolved = true + this.value = value + this.done = true + this.finish() + }).catch(er => this.reject(er)) + } + + reject (er) { + if (this.done) { + return + } + + this.value = er + this.rejected = true + this.done = true + this.finish() + } + + abort (er) { + if (this.done) { + return + } + + this.ready = true + this.finishing = false + this.done = true + this.value = er + // make it clear that this is a problem by doing + // the opposite of what was requested. + this.rejected = !this.expectReject + return this.finish() + } + + finish () { + if (this.ready && this.done && !this.finishing) { + this.finishing = true + this.cb(this) + this.resolve() + } + } +} + +module.exports = Waiter; diff --git a/node_modules/libtap/node_modules/diff/CONTRIBUTING.md b/node_modules/libtap/node_modules/diff/CONTRIBUTING.md new file mode 100644 index 0000000000000..c8c4fe6cc225c --- /dev/null +++ b/node_modules/libtap/node_modules/diff/CONTRIBUTING.md @@ -0,0 +1,39 @@ +# How to Contribute + +## Pull Requests + +We also accept [pull requests][pull-request]! + +Generally we like to see pull requests that + +- Maintain the existing code style +- Are focused on a single change (i.e. avoid large refactoring or style adjustments in untouched code if not the primary goal of the pull request) +- Have [good commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) +- Have tests +- Don't decrease the current code coverage (see coverage/lcov-report/index.html) + +## Building + +``` +npm install +npm test +``` + +The `npm test -- dev` implements watching for tests within Node and `karma start` may be used for manual testing in browsers. + +If you notice any problems, please report them to the GitHub issue tracker at +[http://github.com/kpdecker/jsdiff/issues](http://github.com/kpdecker/jsdiff/issues). + +## Releasing + +JsDiff utilizes the [release yeoman generator][generator-release] to perform most release tasks. + +A full release may be completed with the following: + +``` +yo release +npm publish +``` + +[generator-release]: https://github.com/walmartlabs/generator-release +[pull-request]: https://github.com/kpdecker/jsdiff/pull/new/master diff --git a/node_modules/libtap/node_modules/diff/LICENSE b/node_modules/libtap/node_modules/diff/LICENSE new file mode 100644 index 0000000000000..4e7146ed78a2f --- /dev/null +++ b/node_modules/libtap/node_modules/diff/LICENSE @@ -0,0 +1,31 @@ +Software License Agreement (BSD License) + +Copyright (c) 2009-2015, Kevin Decker + +All rights reserved. + +Redistribution and use of this software in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Kevin Decker nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/node_modules/libtap/node_modules/diff/README.md b/node_modules/libtap/node_modules/diff/README.md new file mode 100644 index 0000000000000..f1bbf2511ef6e --- /dev/null +++ b/node_modules/libtap/node_modules/diff/README.md @@ -0,0 +1,207 @@ +# jsdiff + +[![Build Status](https://secure.travis-ci.org/kpdecker/jsdiff.svg)](http://travis-ci.org/kpdecker/jsdiff) +[![Sauce Test Status](https://saucelabs.com/buildstatus/jsdiff)](https://saucelabs.com/u/jsdiff) + +A javascript text differencing implementation. + +Based on the algorithm proposed in +["An O(ND) Difference Algorithm and its Variations" (Myers, 1986)](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927). + +## Installation +```bash +npm install diff --save +``` + +## API + +* `JsDiff.diffChars(oldStr, newStr[, options])` - diffs two blocks of text, comparing character by character. + + Returns a list of change objects (See below). + + Options + * `ignoreCase`: `true` to ignore casing difference. Defaults to `false`. + +* `JsDiff.diffWords(oldStr, newStr[, options])` - diffs two blocks of text, comparing word by word, ignoring whitespace. + + Returns a list of change objects (See below). + + Options + * `ignoreCase`: Same as in `diffChars`. + +* `JsDiff.diffWordsWithSpace(oldStr, newStr[, options])` - diffs two blocks of text, comparing word by word, treating whitespace as significant. + + Returns a list of change objects (See below). + +* `JsDiff.diffLines(oldStr, newStr[, options])` - diffs two blocks of text, comparing line by line. + + Options + * `ignoreWhitespace`: `true` to ignore leading and trailing whitespace. This is the same as `diffTrimmedLines` + * `newlineIsToken`: `true` to treat newline characters as separate tokens. This allows for changes to the newline structure to occur independently of the line content and to be treated as such. In general this is the more human friendly form of `diffLines` and `diffLines` is better suited for patches and other computer friendly output. + + Returns a list of change objects (See below). + +* `JsDiff.diffTrimmedLines(oldStr, newStr[, options])` - diffs two blocks of text, comparing line by line, ignoring leading and trailing whitespace. + + Returns a list of change objects (See below). + +* `JsDiff.diffSentences(oldStr, newStr[, options])` - diffs two blocks of text, comparing sentence by sentence. + + Returns a list of change objects (See below). + +* `JsDiff.diffCss(oldStr, newStr[, options])` - diffs two blocks of text, comparing CSS tokens. + + Returns a list of change objects (See below). + +* `JsDiff.diffJson(oldObj, newObj[, options])` - diffs two JSON objects, comparing the fields defined on each. The order of fields, etc does not matter in this comparison. + + Returns a list of change objects (See below). + +* `JsDiff.diffArrays(oldArr, newArr[, options])` - diffs two arrays, comparing each item for strict equality (===). + + Options + * `comparator`: `function(left, right)` for custom equality checks + + Returns a list of change objects (See below). + +* `JsDiff.createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader)` - creates a unified diff patch. + + Parameters: + * `oldFileName` : String to be output in the filename section of the patch for the removals + * `newFileName` : String to be output in the filename section of the patch for the additions + * `oldStr` : Original string value + * `newStr` : New string value + * `oldHeader` : Additional information to include in the old file header + * `newHeader` : Additional information to include in the new file header + * `options` : An object with options. Currently, only `context` is supported and describes how many lines of context should be included. + +* `JsDiff.createPatch(fileName, oldStr, newStr, oldHeader, newHeader)` - creates a unified diff patch. + + Just like JsDiff.createTwoFilesPatch, but with oldFileName being equal to newFileName. + + +* `JsDiff.structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options)` - returns an object with an array of hunk objects. + + This method is similar to createTwoFilesPatch, but returns a data structure + suitable for further processing. Parameters are the same as createTwoFilesPatch. The data structure returned may look like this: + + ```js + { + oldFileName: 'oldfile', newFileName: 'newfile', + oldHeader: 'header1', newHeader: 'header2', + hunks: [{ + oldStart: 1, oldLines: 3, newStart: 1, newLines: 3, + lines: [' line2', ' line3', '-line4', '+line5', '\\ No newline at end of file'], + }] + } + ``` + +* `JsDiff.applyPatch(source, patch[, options])` - applies a unified diff patch. + + Return a string containing new version of provided data. `patch` may be a string diff or the output from the `parsePatch` or `structuredPatch` methods. + + The optional `options` object may have the following keys: + + - `fuzzFactor`: Number of lines that are allowed to differ before rejecting a patch. Defaults to 0. + - `compareLine(lineNumber, line, operation, patchContent)`: Callback used to compare to given lines to determine if they should be considered equal when patching. Defaults to strict equality but may be overridden to provide fuzzier comparison. Should return false if the lines should be rejected. + +* `JsDiff.applyPatches(patch, options)` - applies one or more patches. + + This method will iterate over the contents of the patch and apply to data provided through callbacks. The general flow for each patch index is: + + - `options.loadFile(index, callback)` is called. The caller should then load the contents of the file and then pass that to the `callback(err, data)` callback. Passing an `err` will terminate further patch execution. + - `options.patched(index, content, callback)` is called once the patch has been applied. `content` will be the return value from `applyPatch`. When it's ready, the caller should call `callback(err)` callback. Passing an `err` will terminate further patch execution. + + Once all patches have been applied or an error occurs, the `options.complete(err)` callback is made. + +* `JsDiff.parsePatch(diffStr)` - Parses a patch into structured data + + Return a JSON object representation of the a patch, suitable for use with the `applyPatch` method. This parses to the same structure returned by `JsDiff.structuredPatch`. + +* `convertChangesToXML(changes)` - converts a list of changes to a serialized XML format + + +All methods above which accept the optional `callback` method will run in sync mode when that parameter is omitted and in async mode when supplied. This allows for larger diffs without blocking the event loop. This may be passed either directly as the final parameter or as the `callback` field in the `options` object. + +### Change Objects +Many of the methods above return change objects. These objects consist of the following fields: + +* `value`: Text content +* `added`: True if the value was inserted into the new string +* `removed`: True if the value was removed from the old string + +Note that some cases may omit a particular flag field. Comparison on the flag fields should always be done in a truthy or falsy manner. + +## Examples + +Basic example in Node + +```js +require('colors'); +var jsdiff = require('diff'); + +var one = 'beep boop'; +var other = 'beep boob blah'; + +var diff = jsdiff.diffChars(one, other); + +diff.forEach(function(part){ + // green for additions, red for deletions + // grey for common parts + var color = part.added ? 'green' : + part.removed ? 'red' : 'grey'; + process.stderr.write(part.value[color]); +}); + +console.log(); +``` +Running the above program should yield + +Node Example + +Basic example in a web page + +```html +

+
+
+```
+
+Open the above .html file in a browser and you should see
+
+Node Example
+
+**[Full online demo](http://kpdecker.github.com/jsdiff)**
+
+## Compatibility
+
+[![Sauce Test Status](https://saucelabs.com/browser-matrix/jsdiff.svg)](https://saucelabs.com/u/jsdiff)
+
+jsdiff supports all ES3 environments with some known issues on IE8 and below. Under these browsers some diff algorithms such as word diff and others may fail due to lack of support for capturing groups in the `split` operation.
+
+## License
+
+See [LICENSE](https://github.com/kpdecker/jsdiff/blob/master/LICENSE).
diff --git a/node_modules/libtap/node_modules/diff/dist/diff.js b/node_modules/libtap/node_modules/diff/dist/diff.js
new file mode 100644
index 0000000000000..03571caa7e9e6
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/dist/diff.js
@@ -0,0 +1,1585 @@
+/*!
+
+ diff v4.0.1
+
+Software License Agreement (BSD License)
+
+Copyright (c) 2009-2015, Kevin Decker 
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of Kevin Decker nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+@license
+*/
+(function (global, factory) {
+  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+  typeof define === 'function' && define.amd ? define(['exports'], factory) :
+  (global = global || self, factory(global.Diff = {}));
+}(this, function (exports) { 'use strict';
+
+  function Diff() {}
+  Diff.prototype = {
+    diff: function diff(oldString, newString) {
+      var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
+      var callback = options.callback;
+
+      if (typeof options === 'function') {
+        callback = options;
+        options = {};
+      }
+
+      this.options = options;
+      var self = this;
+
+      function done(value) {
+        if (callback) {
+          setTimeout(function () {
+            callback(undefined, value);
+          }, 0);
+          return true;
+        } else {
+          return value;
+        }
+      } // Allow subclasses to massage the input prior to running
+
+
+      oldString = this.castInput(oldString);
+      newString = this.castInput(newString);
+      oldString = this.removeEmpty(this.tokenize(oldString));
+      newString = this.removeEmpty(this.tokenize(newString));
+      var newLen = newString.length,
+          oldLen = oldString.length;
+      var editLength = 1;
+      var maxEditLength = newLen + oldLen;
+      var bestPath = [{
+        newPos: -1,
+        components: []
+      }]; // Seed editLength = 0, i.e. the content starts with the same values
+
+      var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
+
+      if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
+        // Identity per the equality and tokenizer
+        return done([{
+          value: this.join(newString),
+          count: newString.length
+        }]);
+      } // Main worker method. checks all permutations of a given edit length for acceptance.
+
+
+      function execEditLength() {
+        for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) {
+          var basePath = void 0;
+
+          var addPath = bestPath[diagonalPath - 1],
+              removePath = bestPath[diagonalPath + 1],
+              _oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
+
+          if (addPath) {
+            // No one else is going to attempt to use this value, clear it
+            bestPath[diagonalPath - 1] = undefined;
+          }
+
+          var canAdd = addPath && addPath.newPos + 1 < newLen,
+              canRemove = removePath && 0 <= _oldPos && _oldPos < oldLen;
+
+          if (!canAdd && !canRemove) {
+            // If this path is a terminal then prune
+            bestPath[diagonalPath] = undefined;
+            continue;
+          } // Select the diagonal that we want to branch from. We select the prior
+          // path whose position in the new string is the farthest from the origin
+          // and does not pass the bounds of the diff graph
+
+
+          if (!canAdd || canRemove && addPath.newPos < removePath.newPos) {
+            basePath = clonePath(removePath);
+            self.pushComponent(basePath.components, undefined, true);
+          } else {
+            basePath = addPath; // No need to clone, we've pulled it from the list
+
+            basePath.newPos++;
+            self.pushComponent(basePath.components, true, undefined);
+          }
+
+          _oldPos = self.extractCommon(basePath, newString, oldString, diagonalPath); // If we have hit the end of both strings, then we are done
+
+          if (basePath.newPos + 1 >= newLen && _oldPos + 1 >= oldLen) {
+            return done(buildValues(self, basePath.components, newString, oldString, self.useLongestToken));
+          } else {
+            // Otherwise track this path as a potential candidate and continue.
+            bestPath[diagonalPath] = basePath;
+          }
+        }
+
+        editLength++;
+      } // Performs the length of edit iteration. Is a bit fugly as this has to support the
+      // sync and async mode which is never fun. Loops over execEditLength until a value
+      // is produced.
+
+
+      if (callback) {
+        (function exec() {
+          setTimeout(function () {
+            // This should not happen, but we want to be safe.
+
+            /* istanbul ignore next */
+            if (editLength > maxEditLength) {
+              return callback();
+            }
+
+            if (!execEditLength()) {
+              exec();
+            }
+          }, 0);
+        })();
+      } else {
+        while (editLength <= maxEditLength) {
+          var ret = execEditLength();
+
+          if (ret) {
+            return ret;
+          }
+        }
+      }
+    },
+    pushComponent: function pushComponent(components, added, removed) {
+      var last = components[components.length - 1];
+
+      if (last && last.added === added && last.removed === removed) {
+        // We need to clone here as the component clone operation is just
+        // as shallow array clone
+        components[components.length - 1] = {
+          count: last.count + 1,
+          added: added,
+          removed: removed
+        };
+      } else {
+        components.push({
+          count: 1,
+          added: added,
+          removed: removed
+        });
+      }
+    },
+    extractCommon: function extractCommon(basePath, newString, oldString, diagonalPath) {
+      var newLen = newString.length,
+          oldLen = oldString.length,
+          newPos = basePath.newPos,
+          oldPos = newPos - diagonalPath,
+          commonCount = 0;
+
+      while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) {
+        newPos++;
+        oldPos++;
+        commonCount++;
+      }
+
+      if (commonCount) {
+        basePath.components.push({
+          count: commonCount
+        });
+      }
+
+      basePath.newPos = newPos;
+      return oldPos;
+    },
+    equals: function equals(left, right) {
+      if (this.options.comparator) {
+        return this.options.comparator(left, right);
+      } else {
+        return left === right || this.options.ignoreCase && left.toLowerCase() === right.toLowerCase();
+      }
+    },
+    removeEmpty: function removeEmpty(array) {
+      var ret = [];
+
+      for (var i = 0; i < array.length; i++) {
+        if (array[i]) {
+          ret.push(array[i]);
+        }
+      }
+
+      return ret;
+    },
+    castInput: function castInput(value) {
+      return value;
+    },
+    tokenize: function tokenize(value) {
+      return value.split('');
+    },
+    join: function join(chars) {
+      return chars.join('');
+    }
+  };
+
+  function buildValues(diff, components, newString, oldString, useLongestToken) {
+    var componentPos = 0,
+        componentLen = components.length,
+        newPos = 0,
+        oldPos = 0;
+
+    for (; componentPos < componentLen; componentPos++) {
+      var component = components[componentPos];
+
+      if (!component.removed) {
+        if (!component.added && useLongestToken) {
+          var value = newString.slice(newPos, newPos + component.count);
+          value = value.map(function (value, i) {
+            var oldValue = oldString[oldPos + i];
+            return oldValue.length > value.length ? oldValue : value;
+          });
+          component.value = diff.join(value);
+        } else {
+          component.value = diff.join(newString.slice(newPos, newPos + component.count));
+        }
+
+        newPos += component.count; // Common case
+
+        if (!component.added) {
+          oldPos += component.count;
+        }
+      } else {
+        component.value = diff.join(oldString.slice(oldPos, oldPos + component.count));
+        oldPos += component.count; // Reverse add and remove so removes are output first to match common convention
+        // The diffing algorithm is tied to add then remove output and this is the simplest
+        // route to get the desired output with minimal overhead.
+
+        if (componentPos && components[componentPos - 1].added) {
+          var tmp = components[componentPos - 1];
+          components[componentPos - 1] = components[componentPos];
+          components[componentPos] = tmp;
+        }
+      }
+    } // Special case handle for when one terminal is ignored (i.e. whitespace).
+    // For this case we merge the terminal into the prior string and drop the change.
+    // This is only available for string mode.
+
+
+    var lastComponent = components[componentLen - 1];
+
+    if (componentLen > 1 && typeof lastComponent.value === 'string' && (lastComponent.added || lastComponent.removed) && diff.equals('', lastComponent.value)) {
+      components[componentLen - 2].value += lastComponent.value;
+      components.pop();
+    }
+
+    return components;
+  }
+
+  function clonePath(path) {
+    return {
+      newPos: path.newPos,
+      components: path.components.slice(0)
+    };
+  }
+
+  var characterDiff = new Diff();
+  function diffChars(oldStr, newStr, options) {
+    return characterDiff.diff(oldStr, newStr, options);
+  }
+
+  function generateOptions(options, defaults) {
+    if (typeof options === 'function') {
+      defaults.callback = options;
+    } else if (options) {
+      for (var name in options) {
+        /* istanbul ignore else */
+        if (options.hasOwnProperty(name)) {
+          defaults[name] = options[name];
+        }
+      }
+    }
+
+    return defaults;
+  }
+
+  //
+  // Ranges and exceptions:
+  // Latin-1 Supplement, 0080–00FF
+  //  - U+00D7  × Multiplication sign
+  //  - U+00F7  ÷ Division sign
+  // Latin Extended-A, 0100–017F
+  // Latin Extended-B, 0180–024F
+  // IPA Extensions, 0250–02AF
+  // Spacing Modifier Letters, 02B0–02FF
+  //  - U+02C7  ˇ ˇ  Caron
+  //  - U+02D8  ˘ ˘  Breve
+  //  - U+02D9  ˙ ˙  Dot Above
+  //  - U+02DA  ˚ ˚  Ring Above
+  //  - U+02DB  ˛ ˛  Ogonek
+  //  - U+02DC  ˜ ˜  Small Tilde
+  //  - U+02DD  ˝ ˝  Double Acute Accent
+  // Latin Extended Additional, 1E00–1EFF
+
+  var extendedWordChars = /^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/;
+  var reWhitespace = /\S/;
+  var wordDiff = new Diff();
+
+  wordDiff.equals = function (left, right) {
+    if (this.options.ignoreCase) {
+      left = left.toLowerCase();
+      right = right.toLowerCase();
+    }
+
+    return left === right || this.options.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right);
+  };
+
+  wordDiff.tokenize = function (value) {
+    var tokens = value.split(/(\s+|[()[\]{}'"]|\b)/); // Join the boundary splits that we do not consider to be boundaries. This is primarily the extended Latin character set.
+
+    for (var i = 0; i < tokens.length - 1; i++) {
+      // If we have an empty string in the next field and we have only word chars before and after, merge
+      if (!tokens[i + 1] && tokens[i + 2] && extendedWordChars.test(tokens[i]) && extendedWordChars.test(tokens[i + 2])) {
+        tokens[i] += tokens[i + 2];
+        tokens.splice(i + 1, 2);
+        i--;
+      }
+    }
+
+    return tokens;
+  };
+
+  function diffWords(oldStr, newStr, options) {
+    options = generateOptions(options, {
+      ignoreWhitespace: true
+    });
+    return wordDiff.diff(oldStr, newStr, options);
+  }
+  function diffWordsWithSpace(oldStr, newStr, options) {
+    return wordDiff.diff(oldStr, newStr, options);
+  }
+
+  var lineDiff = new Diff();
+
+  lineDiff.tokenize = function (value) {
+    var retLines = [],
+        linesAndNewlines = value.split(/(\n|\r\n)/); // Ignore the final empty token that occurs if the string ends with a new line
+
+    if (!linesAndNewlines[linesAndNewlines.length - 1]) {
+      linesAndNewlines.pop();
+    } // Merge the content and line separators into single tokens
+
+
+    for (var i = 0; i < linesAndNewlines.length; i++) {
+      var line = linesAndNewlines[i];
+
+      if (i % 2 && !this.options.newlineIsToken) {
+        retLines[retLines.length - 1] += line;
+      } else {
+        if (this.options.ignoreWhitespace) {
+          line = line.trim();
+        }
+
+        retLines.push(line);
+      }
+    }
+
+    return retLines;
+  };
+
+  function diffLines(oldStr, newStr, callback) {
+    return lineDiff.diff(oldStr, newStr, callback);
+  }
+  function diffTrimmedLines(oldStr, newStr, callback) {
+    var options = generateOptions(callback, {
+      ignoreWhitespace: true
+    });
+    return lineDiff.diff(oldStr, newStr, options);
+  }
+
+  var sentenceDiff = new Diff();
+
+  sentenceDiff.tokenize = function (value) {
+    return value.split(/(\S.+?[.!?])(?=\s+|$)/);
+  };
+
+  function diffSentences(oldStr, newStr, callback) {
+    return sentenceDiff.diff(oldStr, newStr, callback);
+  }
+
+  var cssDiff = new Diff();
+
+  cssDiff.tokenize = function (value) {
+    return value.split(/([{}:;,]|\s+)/);
+  };
+
+  function diffCss(oldStr, newStr, callback) {
+    return cssDiff.diff(oldStr, newStr, callback);
+  }
+
+  function _typeof(obj) {
+    if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
+      _typeof = function (obj) {
+        return typeof obj;
+      };
+    } else {
+      _typeof = function (obj) {
+        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
+      };
+    }
+
+    return _typeof(obj);
+  }
+
+  function _toConsumableArray(arr) {
+    return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
+  }
+
+  function _arrayWithoutHoles(arr) {
+    if (Array.isArray(arr)) {
+      for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
+
+      return arr2;
+    }
+  }
+
+  function _iterableToArray(iter) {
+    if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
+  }
+
+  function _nonIterableSpread() {
+    throw new TypeError("Invalid attempt to spread non-iterable instance");
+  }
+
+  var objectPrototypeToString = Object.prototype.toString;
+  var jsonDiff = new Diff(); // Discriminate between two lines of pretty-printed, serialized JSON where one of them has a
+  // dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output:
+
+  jsonDiff.useLongestToken = true;
+  jsonDiff.tokenize = lineDiff.tokenize;
+
+  jsonDiff.castInput = function (value) {
+    var _this$options = this.options,
+        undefinedReplacement = _this$options.undefinedReplacement,
+        _this$options$stringi = _this$options.stringifyReplacer,
+        stringifyReplacer = _this$options$stringi === void 0 ? function (k, v) {
+      return typeof v === 'undefined' ? undefinedReplacement : v;
+    } : _this$options$stringi;
+    return typeof value === 'string' ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), stringifyReplacer, '  ');
+  };
+
+  jsonDiff.equals = function (left, right) {
+    return Diff.prototype.equals.call(jsonDiff, left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1'));
+  };
+
+  function diffJson(oldObj, newObj, options) {
+    return jsonDiff.diff(oldObj, newObj, options);
+  } // This function handles the presence of circular references by bailing out when encountering an
+  // object that is already on the "stack" of items being processed. Accepts an optional replacer
+
+  function canonicalize(obj, stack, replacementStack, replacer, key) {
+    stack = stack || [];
+    replacementStack = replacementStack || [];
+
+    if (replacer) {
+      obj = replacer(key, obj);
+    }
+
+    var i;
+
+    for (i = 0; i < stack.length; i += 1) {
+      if (stack[i] === obj) {
+        return replacementStack[i];
+      }
+    }
+
+    var canonicalizedObj;
+
+    if ('[object Array]' === objectPrototypeToString.call(obj)) {
+      stack.push(obj);
+      canonicalizedObj = new Array(obj.length);
+      replacementStack.push(canonicalizedObj);
+
+      for (i = 0; i < obj.length; i += 1) {
+        canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack, replacer, key);
+      }
+
+      stack.pop();
+      replacementStack.pop();
+      return canonicalizedObj;
+    }
+
+    if (obj && obj.toJSON) {
+      obj = obj.toJSON();
+    }
+
+    if (_typeof(obj) === 'object' && obj !== null) {
+      stack.push(obj);
+      canonicalizedObj = {};
+      replacementStack.push(canonicalizedObj);
+
+      var sortedKeys = [],
+          _key;
+
+      for (_key in obj) {
+        /* istanbul ignore else */
+        if (obj.hasOwnProperty(_key)) {
+          sortedKeys.push(_key);
+        }
+      }
+
+      sortedKeys.sort();
+
+      for (i = 0; i < sortedKeys.length; i += 1) {
+        _key = sortedKeys[i];
+        canonicalizedObj[_key] = canonicalize(obj[_key], stack, replacementStack, replacer, _key);
+      }
+
+      stack.pop();
+      replacementStack.pop();
+    } else {
+      canonicalizedObj = obj;
+    }
+
+    return canonicalizedObj;
+  }
+
+  var arrayDiff = new Diff();
+
+  arrayDiff.tokenize = function (value) {
+    return value.slice();
+  };
+
+  arrayDiff.join = arrayDiff.removeEmpty = function (value) {
+    return value;
+  };
+
+  function diffArrays(oldArr, newArr, callback) {
+    return arrayDiff.diff(oldArr, newArr, callback);
+  }
+
+  function parsePatch(uniDiff) {
+    var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+    var diffstr = uniDiff.split(/\r\n|[\n\v\f\r\x85]/),
+        delimiters = uniDiff.match(/\r\n|[\n\v\f\r\x85]/g) || [],
+        list = [],
+        i = 0;
+
+    function parseIndex() {
+      var index = {};
+      list.push(index); // Parse diff metadata
+
+      while (i < diffstr.length) {
+        var line = diffstr[i]; // File header found, end parsing diff metadata
+
+        if (/^(\-\-\-|\+\+\+|@@)\s/.test(line)) {
+          break;
+        } // Diff index
+
+
+        var header = /^(?:Index:|diff(?: -r \w+)+)\s+(.+?)\s*$/.exec(line);
+
+        if (header) {
+          index.index = header[1];
+        }
+
+        i++;
+      } // Parse file headers if they are defined. Unified diff requires them, but
+      // there's no technical issues to have an isolated hunk without file header
+
+
+      parseFileHeader(index);
+      parseFileHeader(index); // Parse hunks
+
+      index.hunks = [];
+
+      while (i < diffstr.length) {
+        var _line = diffstr[i];
+
+        if (/^(Index:|diff|\-\-\-|\+\+\+)\s/.test(_line)) {
+          break;
+        } else if (/^@@/.test(_line)) {
+          index.hunks.push(parseHunk());
+        } else if (_line && options.strict) {
+          // Ignore unexpected content unless in strict mode
+          throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(_line));
+        } else {
+          i++;
+        }
+      }
+    } // Parses the --- and +++ headers, if none are found, no lines
+    // are consumed.
+
+
+    function parseFileHeader(index) {
+      var fileHeader = /^(---|\+\+\+)\s+(.*)$/.exec(diffstr[i]);
+
+      if (fileHeader) {
+        var keyPrefix = fileHeader[1] === '---' ? 'old' : 'new';
+        var data = fileHeader[2].split('\t', 2);
+        var fileName = data[0].replace(/\\\\/g, '\\');
+
+        if (/^".*"$/.test(fileName)) {
+          fileName = fileName.substr(1, fileName.length - 2);
+        }
+
+        index[keyPrefix + 'FileName'] = fileName;
+        index[keyPrefix + 'Header'] = (data[1] || '').trim();
+        i++;
+      }
+    } // Parses a hunk
+    // This assumes that we are at the start of a hunk.
+
+
+    function parseHunk() {
+      var chunkHeaderIndex = i,
+          chunkHeaderLine = diffstr[i++],
+          chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
+      var hunk = {
+        oldStart: +chunkHeader[1],
+        oldLines: +chunkHeader[2] || 1,
+        newStart: +chunkHeader[3],
+        newLines: +chunkHeader[4] || 1,
+        lines: [],
+        linedelimiters: []
+      };
+      var addCount = 0,
+          removeCount = 0;
+
+      for (; i < diffstr.length; i++) {
+        // Lines starting with '---' could be mistaken for the "remove line" operation
+        // But they could be the header for the next file. Therefore prune such cases out.
+        if (diffstr[i].indexOf('--- ') === 0 && i + 2 < diffstr.length && diffstr[i + 1].indexOf('+++ ') === 0 && diffstr[i + 2].indexOf('@@') === 0) {
+          break;
+        }
+
+        var operation = diffstr[i].length == 0 && i != diffstr.length - 1 ? ' ' : diffstr[i][0];
+
+        if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') {
+          hunk.lines.push(diffstr[i]);
+          hunk.linedelimiters.push(delimiters[i] || '\n');
+
+          if (operation === '+') {
+            addCount++;
+          } else if (operation === '-') {
+            removeCount++;
+          } else if (operation === ' ') {
+            addCount++;
+            removeCount++;
+          }
+        } else {
+          break;
+        }
+      } // Handle the empty block count case
+
+
+      if (!addCount && hunk.newLines === 1) {
+        hunk.newLines = 0;
+      }
+
+      if (!removeCount && hunk.oldLines === 1) {
+        hunk.oldLines = 0;
+      } // Perform optional sanity checking
+
+
+      if (options.strict) {
+        if (addCount !== hunk.newLines) {
+          throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
+        }
+
+        if (removeCount !== hunk.oldLines) {
+          throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
+        }
+      }
+
+      return hunk;
+    }
+
+    while (i < diffstr.length) {
+      parseIndex();
+    }
+
+    return list;
+  }
+
+  // Iterator that traverses in the range of [min, max], stepping
+  // by distance from a given start position. I.e. for [0, 4], with
+  // start of 2, this will iterate 2, 3, 1, 4, 0.
+  function distanceIterator (start, minLine, maxLine) {
+    var wantForward = true,
+        backwardExhausted = false,
+        forwardExhausted = false,
+        localOffset = 1;
+    return function iterator() {
+      if (wantForward && !forwardExhausted) {
+        if (backwardExhausted) {
+          localOffset++;
+        } else {
+          wantForward = false;
+        } // Check if trying to fit beyond text length, and if not, check it fits
+        // after offset location (or desired location on first iteration)
+
+
+        if (start + localOffset <= maxLine) {
+          return localOffset;
+        }
+
+        forwardExhausted = true;
+      }
+
+      if (!backwardExhausted) {
+        if (!forwardExhausted) {
+          wantForward = true;
+        } // Check if trying to fit before text beginning, and if not, check it fits
+        // before offset location
+
+
+        if (minLine <= start - localOffset) {
+          return -localOffset++;
+        }
+
+        backwardExhausted = true;
+        return iterator();
+      } // We tried to fit hunk before text beginning and beyond text length, then
+      // hunk can't fit on the text. Return undefined
+
+    };
+  }
+
+  function applyPatch(source, uniDiff) {
+    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
+
+    if (typeof uniDiff === 'string') {
+      uniDiff = parsePatch(uniDiff);
+    }
+
+    if (Array.isArray(uniDiff)) {
+      if (uniDiff.length > 1) {
+        throw new Error('applyPatch only works with a single input.');
+      }
+
+      uniDiff = uniDiff[0];
+    } // Apply the diff to the input
+
+
+    var lines = source.split(/\r\n|[\n\v\f\r\x85]/),
+        delimiters = source.match(/\r\n|[\n\v\f\r\x85]/g) || [],
+        hunks = uniDiff.hunks,
+        compareLine = options.compareLine || function (lineNumber, line, operation, patchContent) {
+      return line === patchContent;
+    },
+        errorCount = 0,
+        fuzzFactor = options.fuzzFactor || 0,
+        minLine = 0,
+        offset = 0,
+        removeEOFNL,
+        addEOFNL;
+    /**
+     * Checks if the hunk exactly fits on the provided location
+     */
+
+
+    function hunkFits(hunk, toPos) {
+      for (var j = 0; j < hunk.lines.length; j++) {
+        var line = hunk.lines[j],
+            operation = line.length > 0 ? line[0] : ' ',
+            content = line.length > 0 ? line.substr(1) : line;
+
+        if (operation === ' ' || operation === '-') {
+          // Context sanity check
+          if (!compareLine(toPos + 1, lines[toPos], operation, content)) {
+            errorCount++;
+
+            if (errorCount > fuzzFactor) {
+              return false;
+            }
+          }
+
+          toPos++;
+        }
+      }
+
+      return true;
+    } // Search best fit offsets for each hunk based on the previous ones
+
+
+    for (var i = 0; i < hunks.length; i++) {
+      var hunk = hunks[i],
+          maxLine = lines.length - hunk.oldLines,
+          localOffset = 0,
+          toPos = offset + hunk.oldStart - 1;
+      var iterator = distanceIterator(toPos, minLine, maxLine);
+
+      for (; localOffset !== undefined; localOffset = iterator()) {
+        if (hunkFits(hunk, toPos + localOffset)) {
+          hunk.offset = offset += localOffset;
+          break;
+        }
+      }
+
+      if (localOffset === undefined) {
+        return false;
+      } // Set lower text limit to end of the current hunk, so next ones don't try
+      // to fit over already patched text
+
+
+      minLine = hunk.offset + hunk.oldStart + hunk.oldLines;
+    } // Apply patch hunks
+
+
+    var diffOffset = 0;
+
+    for (var _i = 0; _i < hunks.length; _i++) {
+      var _hunk = hunks[_i],
+          _toPos = _hunk.oldStart + _hunk.offset + diffOffset - 1;
+
+      diffOffset += _hunk.newLines - _hunk.oldLines;
+
+      if (_toPos < 0) {
+        // Creating a new file
+        _toPos = 0;
+      }
+
+      for (var j = 0; j < _hunk.lines.length; j++) {
+        var line = _hunk.lines[j],
+            operation = line.length > 0 ? line[0] : ' ',
+            content = line.length > 0 ? line.substr(1) : line,
+            delimiter = _hunk.linedelimiters[j];
+
+        if (operation === ' ') {
+          _toPos++;
+        } else if (operation === '-') {
+          lines.splice(_toPos, 1);
+          delimiters.splice(_toPos, 1);
+          /* istanbul ignore else */
+        } else if (operation === '+') {
+          lines.splice(_toPos, 0, content);
+          delimiters.splice(_toPos, 0, delimiter);
+          _toPos++;
+        } else if (operation === '\\') {
+          var previousOperation = _hunk.lines[j - 1] ? _hunk.lines[j - 1][0] : null;
+
+          if (previousOperation === '+') {
+            removeEOFNL = true;
+          } else if (previousOperation === '-') {
+            addEOFNL = true;
+          }
+        }
+      }
+    } // Handle EOFNL insertion/removal
+
+
+    if (removeEOFNL) {
+      while (!lines[lines.length - 1]) {
+        lines.pop();
+        delimiters.pop();
+      }
+    } else if (addEOFNL) {
+      lines.push('');
+      delimiters.push('\n');
+    }
+
+    for (var _k = 0; _k < lines.length - 1; _k++) {
+      lines[_k] = lines[_k] + delimiters[_k];
+    }
+
+    return lines.join('');
+  } // Wrapper that supports multiple file patches via callbacks.
+
+  function applyPatches(uniDiff, options) {
+    if (typeof uniDiff === 'string') {
+      uniDiff = parsePatch(uniDiff);
+    }
+
+    var currentIndex = 0;
+
+    function processIndex() {
+      var index = uniDiff[currentIndex++];
+
+      if (!index) {
+        return options.complete();
+      }
+
+      options.loadFile(index, function (err, data) {
+        if (err) {
+          return options.complete(err);
+        }
+
+        var updatedContent = applyPatch(data, index, options);
+        options.patched(index, updatedContent, function (err) {
+          if (err) {
+            return options.complete(err);
+          }
+
+          processIndex();
+        });
+      });
+    }
+
+    processIndex();
+  }
+
+  function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
+    if (!options) {
+      options = {};
+    }
+
+    if (typeof options.context === 'undefined') {
+      options.context = 4;
+    }
+
+    var diff = diffLines(oldStr, newStr, options);
+    diff.push({
+      value: '',
+      lines: []
+    }); // Append an empty value to make cleanup easier
+
+    function contextLines(lines) {
+      return lines.map(function (entry) {
+        return ' ' + entry;
+      });
+    }
+
+    var hunks = [];
+    var oldRangeStart = 0,
+        newRangeStart = 0,
+        curRange = [],
+        oldLine = 1,
+        newLine = 1;
+
+    var _loop = function _loop(i) {
+      var current = diff[i],
+          lines = current.lines || current.value.replace(/\n$/, '').split('\n');
+      current.lines = lines;
+
+      if (current.added || current.removed) {
+        var _curRange;
+
+        // If we have previous context, start with that
+        if (!oldRangeStart) {
+          var prev = diff[i - 1];
+          oldRangeStart = oldLine;
+          newRangeStart = newLine;
+
+          if (prev) {
+            curRange = options.context > 0 ? contextLines(prev.lines.slice(-options.context)) : [];
+            oldRangeStart -= curRange.length;
+            newRangeStart -= curRange.length;
+          }
+        } // Output our changes
+
+
+        (_curRange = curRange).push.apply(_curRange, _toConsumableArray(lines.map(function (entry) {
+          return (current.added ? '+' : '-') + entry;
+        }))); // Track the updated file position
+
+
+        if (current.added) {
+          newLine += lines.length;
+        } else {
+          oldLine += lines.length;
+        }
+      } else {
+        // Identical context lines. Track line changes
+        if (oldRangeStart) {
+          // Close out any changes that have been output (or join overlapping)
+          if (lines.length <= options.context * 2 && i < diff.length - 2) {
+            var _curRange2;
+
+            // Overlapping
+            (_curRange2 = curRange).push.apply(_curRange2, _toConsumableArray(contextLines(lines)));
+          } else {
+            var _curRange3;
+
+            // end the range and output
+            var contextSize = Math.min(lines.length, options.context);
+
+            (_curRange3 = curRange).push.apply(_curRange3, _toConsumableArray(contextLines(lines.slice(0, contextSize))));
+
+            var hunk = {
+              oldStart: oldRangeStart,
+              oldLines: oldLine - oldRangeStart + contextSize,
+              newStart: newRangeStart,
+              newLines: newLine - newRangeStart + contextSize,
+              lines: curRange
+            };
+
+            if (i >= diff.length - 2 && lines.length <= options.context) {
+              // EOF is inside this hunk
+              var oldEOFNewline = /\n$/.test(oldStr);
+              var newEOFNewline = /\n$/.test(newStr);
+              var noNlBeforeAdds = lines.length == 0 && curRange.length > hunk.oldLines;
+
+              if (!oldEOFNewline && noNlBeforeAdds) {
+                // special case: old has no eol and no trailing context; no-nl can end up before adds
+                curRange.splice(hunk.oldLines, 0, '\\ No newline at end of file');
+              }
+
+              if (!oldEOFNewline && !noNlBeforeAdds || !newEOFNewline) {
+                curRange.push('\\ No newline at end of file');
+              }
+            }
+
+            hunks.push(hunk);
+            oldRangeStart = 0;
+            newRangeStart = 0;
+            curRange = [];
+          }
+        }
+
+        oldLine += lines.length;
+        newLine += lines.length;
+      }
+    };
+
+    for (var i = 0; i < diff.length; i++) {
+      _loop(i);
+    }
+
+    return {
+      oldFileName: oldFileName,
+      newFileName: newFileName,
+      oldHeader: oldHeader,
+      newHeader: newHeader,
+      hunks: hunks
+    };
+  }
+  function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
+    var diff = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options);
+    var ret = [];
+
+    if (oldFileName == newFileName) {
+      ret.push('Index: ' + oldFileName);
+    }
+
+    ret.push('===================================================================');
+    ret.push('--- ' + diff.oldFileName + (typeof diff.oldHeader === 'undefined' ? '' : '\t' + diff.oldHeader));
+    ret.push('+++ ' + diff.newFileName + (typeof diff.newHeader === 'undefined' ? '' : '\t' + diff.newHeader));
+
+    for (var i = 0; i < diff.hunks.length; i++) {
+      var hunk = diff.hunks[i];
+      ret.push('@@ -' + hunk.oldStart + ',' + hunk.oldLines + ' +' + hunk.newStart + ',' + hunk.newLines + ' @@');
+      ret.push.apply(ret, hunk.lines);
+    }
+
+    return ret.join('\n') + '\n';
+  }
+  function createPatch(fileName, oldStr, newStr, oldHeader, newHeader, options) {
+    return createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader, options);
+  }
+
+  function arrayEqual(a, b) {
+    if (a.length !== b.length) {
+      return false;
+    }
+
+    return arrayStartsWith(a, b);
+  }
+  function arrayStartsWith(array, start) {
+    if (start.length > array.length) {
+      return false;
+    }
+
+    for (var i = 0; i < start.length; i++) {
+      if (start[i] !== array[i]) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  function calcLineCount(hunk) {
+    var _calcOldNewLineCount = calcOldNewLineCount(hunk.lines),
+        oldLines = _calcOldNewLineCount.oldLines,
+        newLines = _calcOldNewLineCount.newLines;
+
+    if (oldLines !== undefined) {
+      hunk.oldLines = oldLines;
+    } else {
+      delete hunk.oldLines;
+    }
+
+    if (newLines !== undefined) {
+      hunk.newLines = newLines;
+    } else {
+      delete hunk.newLines;
+    }
+  }
+  function merge(mine, theirs, base) {
+    mine = loadPatch(mine, base);
+    theirs = loadPatch(theirs, base);
+    var ret = {}; // For index we just let it pass through as it doesn't have any necessary meaning.
+    // Leaving sanity checks on this to the API consumer that may know more about the
+    // meaning in their own context.
+
+    if (mine.index || theirs.index) {
+      ret.index = mine.index || theirs.index;
+    }
+
+    if (mine.newFileName || theirs.newFileName) {
+      if (!fileNameChanged(mine)) {
+        // No header or no change in ours, use theirs (and ours if theirs does not exist)
+        ret.oldFileName = theirs.oldFileName || mine.oldFileName;
+        ret.newFileName = theirs.newFileName || mine.newFileName;
+        ret.oldHeader = theirs.oldHeader || mine.oldHeader;
+        ret.newHeader = theirs.newHeader || mine.newHeader;
+      } else if (!fileNameChanged(theirs)) {
+        // No header or no change in theirs, use ours
+        ret.oldFileName = mine.oldFileName;
+        ret.newFileName = mine.newFileName;
+        ret.oldHeader = mine.oldHeader;
+        ret.newHeader = mine.newHeader;
+      } else {
+        // Both changed... figure it out
+        ret.oldFileName = selectField(ret, mine.oldFileName, theirs.oldFileName);
+        ret.newFileName = selectField(ret, mine.newFileName, theirs.newFileName);
+        ret.oldHeader = selectField(ret, mine.oldHeader, theirs.oldHeader);
+        ret.newHeader = selectField(ret, mine.newHeader, theirs.newHeader);
+      }
+    }
+
+    ret.hunks = [];
+    var mineIndex = 0,
+        theirsIndex = 0,
+        mineOffset = 0,
+        theirsOffset = 0;
+
+    while (mineIndex < mine.hunks.length || theirsIndex < theirs.hunks.length) {
+      var mineCurrent = mine.hunks[mineIndex] || {
+        oldStart: Infinity
+      },
+          theirsCurrent = theirs.hunks[theirsIndex] || {
+        oldStart: Infinity
+      };
+
+      if (hunkBefore(mineCurrent, theirsCurrent)) {
+        // This patch does not overlap with any of the others, yay.
+        ret.hunks.push(cloneHunk(mineCurrent, mineOffset));
+        mineIndex++;
+        theirsOffset += mineCurrent.newLines - mineCurrent.oldLines;
+      } else if (hunkBefore(theirsCurrent, mineCurrent)) {
+        // This patch does not overlap with any of the others, yay.
+        ret.hunks.push(cloneHunk(theirsCurrent, theirsOffset));
+        theirsIndex++;
+        mineOffset += theirsCurrent.newLines - theirsCurrent.oldLines;
+      } else {
+        // Overlap, merge as best we can
+        var mergedHunk = {
+          oldStart: Math.min(mineCurrent.oldStart, theirsCurrent.oldStart),
+          oldLines: 0,
+          newStart: Math.min(mineCurrent.newStart + mineOffset, theirsCurrent.oldStart + theirsOffset),
+          newLines: 0,
+          lines: []
+        };
+        mergeLines(mergedHunk, mineCurrent.oldStart, mineCurrent.lines, theirsCurrent.oldStart, theirsCurrent.lines);
+        theirsIndex++;
+        mineIndex++;
+        ret.hunks.push(mergedHunk);
+      }
+    }
+
+    return ret;
+  }
+
+  function loadPatch(param, base) {
+    if (typeof param === 'string') {
+      if (/^@@/m.test(param) || /^Index:/m.test(param)) {
+        return parsePatch(param)[0];
+      }
+
+      if (!base) {
+        throw new Error('Must provide a base reference or pass in a patch');
+      }
+
+      return structuredPatch(undefined, undefined, base, param);
+    }
+
+    return param;
+  }
+
+  function fileNameChanged(patch) {
+    return patch.newFileName && patch.newFileName !== patch.oldFileName;
+  }
+
+  function selectField(index, mine, theirs) {
+    if (mine === theirs) {
+      return mine;
+    } else {
+      index.conflict = true;
+      return {
+        mine: mine,
+        theirs: theirs
+      };
+    }
+  }
+
+  function hunkBefore(test, check) {
+    return test.oldStart < check.oldStart && test.oldStart + test.oldLines < check.oldStart;
+  }
+
+  function cloneHunk(hunk, offset) {
+    return {
+      oldStart: hunk.oldStart,
+      oldLines: hunk.oldLines,
+      newStart: hunk.newStart + offset,
+      newLines: hunk.newLines,
+      lines: hunk.lines
+    };
+  }
+
+  function mergeLines(hunk, mineOffset, mineLines, theirOffset, theirLines) {
+    // This will generally result in a conflicted hunk, but there are cases where the context
+    // is the only overlap where we can successfully merge the content here.
+    var mine = {
+      offset: mineOffset,
+      lines: mineLines,
+      index: 0
+    },
+        their = {
+      offset: theirOffset,
+      lines: theirLines,
+      index: 0
+    }; // Handle any leading content
+
+    insertLeading(hunk, mine, their);
+    insertLeading(hunk, their, mine); // Now in the overlap content. Scan through and select the best changes from each.
+
+    while (mine.index < mine.lines.length && their.index < their.lines.length) {
+      var mineCurrent = mine.lines[mine.index],
+          theirCurrent = their.lines[their.index];
+
+      if ((mineCurrent[0] === '-' || mineCurrent[0] === '+') && (theirCurrent[0] === '-' || theirCurrent[0] === '+')) {
+        // Both modified ...
+        mutualChange(hunk, mine, their);
+      } else if (mineCurrent[0] === '+' && theirCurrent[0] === ' ') {
+        var _hunk$lines;
+
+        // Mine inserted
+        (_hunk$lines = hunk.lines).push.apply(_hunk$lines, _toConsumableArray(collectChange(mine)));
+      } else if (theirCurrent[0] === '+' && mineCurrent[0] === ' ') {
+        var _hunk$lines2;
+
+        // Theirs inserted
+        (_hunk$lines2 = hunk.lines).push.apply(_hunk$lines2, _toConsumableArray(collectChange(their)));
+      } else if (mineCurrent[0] === '-' && theirCurrent[0] === ' ') {
+        // Mine removed or edited
+        removal(hunk, mine, their);
+      } else if (theirCurrent[0] === '-' && mineCurrent[0] === ' ') {
+        // Their removed or edited
+        removal(hunk, their, mine, true);
+      } else if (mineCurrent === theirCurrent) {
+        // Context identity
+        hunk.lines.push(mineCurrent);
+        mine.index++;
+        their.index++;
+      } else {
+        // Context mismatch
+        conflict(hunk, collectChange(mine), collectChange(their));
+      }
+    } // Now push anything that may be remaining
+
+
+    insertTrailing(hunk, mine);
+    insertTrailing(hunk, their);
+    calcLineCount(hunk);
+  }
+
+  function mutualChange(hunk, mine, their) {
+    var myChanges = collectChange(mine),
+        theirChanges = collectChange(their);
+
+    if (allRemoves(myChanges) && allRemoves(theirChanges)) {
+      // Special case for remove changes that are supersets of one another
+      if (arrayStartsWith(myChanges, theirChanges) && skipRemoveSuperset(their, myChanges, myChanges.length - theirChanges.length)) {
+        var _hunk$lines3;
+
+        (_hunk$lines3 = hunk.lines).push.apply(_hunk$lines3, _toConsumableArray(myChanges));
+
+        return;
+      } else if (arrayStartsWith(theirChanges, myChanges) && skipRemoveSuperset(mine, theirChanges, theirChanges.length - myChanges.length)) {
+        var _hunk$lines4;
+
+        (_hunk$lines4 = hunk.lines).push.apply(_hunk$lines4, _toConsumableArray(theirChanges));
+
+        return;
+      }
+    } else if (arrayEqual(myChanges, theirChanges)) {
+      var _hunk$lines5;
+
+      (_hunk$lines5 = hunk.lines).push.apply(_hunk$lines5, _toConsumableArray(myChanges));
+
+      return;
+    }
+
+    conflict(hunk, myChanges, theirChanges);
+  }
+
+  function removal(hunk, mine, their, swap) {
+    var myChanges = collectChange(mine),
+        theirChanges = collectContext(their, myChanges);
+
+    if (theirChanges.merged) {
+      var _hunk$lines6;
+
+      (_hunk$lines6 = hunk.lines).push.apply(_hunk$lines6, _toConsumableArray(theirChanges.merged));
+    } else {
+      conflict(hunk, swap ? theirChanges : myChanges, swap ? myChanges : theirChanges);
+    }
+  }
+
+  function conflict(hunk, mine, their) {
+    hunk.conflict = true;
+    hunk.lines.push({
+      conflict: true,
+      mine: mine,
+      theirs: their
+    });
+  }
+
+  function insertLeading(hunk, insert, their) {
+    while (insert.offset < their.offset && insert.index < insert.lines.length) {
+      var line = insert.lines[insert.index++];
+      hunk.lines.push(line);
+      insert.offset++;
+    }
+  }
+
+  function insertTrailing(hunk, insert) {
+    while (insert.index < insert.lines.length) {
+      var line = insert.lines[insert.index++];
+      hunk.lines.push(line);
+    }
+  }
+
+  function collectChange(state) {
+    var ret = [],
+        operation = state.lines[state.index][0];
+
+    while (state.index < state.lines.length) {
+      var line = state.lines[state.index]; // Group additions that are immediately after subtractions and treat them as one "atomic" modify change.
+
+      if (operation === '-' && line[0] === '+') {
+        operation = '+';
+      }
+
+      if (operation === line[0]) {
+        ret.push(line);
+        state.index++;
+      } else {
+        break;
+      }
+    }
+
+    return ret;
+  }
+
+  function collectContext(state, matchChanges) {
+    var changes = [],
+        merged = [],
+        matchIndex = 0,
+        contextChanges = false,
+        conflicted = false;
+
+    while (matchIndex < matchChanges.length && state.index < state.lines.length) {
+      var change = state.lines[state.index],
+          match = matchChanges[matchIndex]; // Once we've hit our add, then we are done
+
+      if (match[0] === '+') {
+        break;
+      }
+
+      contextChanges = contextChanges || change[0] !== ' ';
+      merged.push(match);
+      matchIndex++; // Consume any additions in the other block as a conflict to attempt
+      // to pull in the remaining context after this
+
+      if (change[0] === '+') {
+        conflicted = true;
+
+        while (change[0] === '+') {
+          changes.push(change);
+          change = state.lines[++state.index];
+        }
+      }
+
+      if (match.substr(1) === change.substr(1)) {
+        changes.push(change);
+        state.index++;
+      } else {
+        conflicted = true;
+      }
+    }
+
+    if ((matchChanges[matchIndex] || '')[0] === '+' && contextChanges) {
+      conflicted = true;
+    }
+
+    if (conflicted) {
+      return changes;
+    }
+
+    while (matchIndex < matchChanges.length) {
+      merged.push(matchChanges[matchIndex++]);
+    }
+
+    return {
+      merged: merged,
+      changes: changes
+    };
+  }
+
+  function allRemoves(changes) {
+    return changes.reduce(function (prev, change) {
+      return prev && change[0] === '-';
+    }, true);
+  }
+
+  function skipRemoveSuperset(state, removeChanges, delta) {
+    for (var i = 0; i < delta; i++) {
+      var changeContent = removeChanges[removeChanges.length - delta + i].substr(1);
+
+      if (state.lines[state.index + i] !== ' ' + changeContent) {
+        return false;
+      }
+    }
+
+    state.index += delta;
+    return true;
+  }
+
+  function calcOldNewLineCount(lines) {
+    var oldLines = 0;
+    var newLines = 0;
+    lines.forEach(function (line) {
+      if (typeof line !== 'string') {
+        var myCount = calcOldNewLineCount(line.mine);
+        var theirCount = calcOldNewLineCount(line.theirs);
+
+        if (oldLines !== undefined) {
+          if (myCount.oldLines === theirCount.oldLines) {
+            oldLines += myCount.oldLines;
+          } else {
+            oldLines = undefined;
+          }
+        }
+
+        if (newLines !== undefined) {
+          if (myCount.newLines === theirCount.newLines) {
+            newLines += myCount.newLines;
+          } else {
+            newLines = undefined;
+          }
+        }
+      } else {
+        if (newLines !== undefined && (line[0] === '+' || line[0] === ' ')) {
+          newLines++;
+        }
+
+        if (oldLines !== undefined && (line[0] === '-' || line[0] === ' ')) {
+          oldLines++;
+        }
+      }
+    });
+    return {
+      oldLines: oldLines,
+      newLines: newLines
+    };
+  }
+
+  // See: http://code.google.com/p/google-diff-match-patch/wiki/API
+  function convertChangesToDMP(changes) {
+    var ret = [],
+        change,
+        operation;
+
+    for (var i = 0; i < changes.length; i++) {
+      change = changes[i];
+
+      if (change.added) {
+        operation = 1;
+      } else if (change.removed) {
+        operation = -1;
+      } else {
+        operation = 0;
+      }
+
+      ret.push([operation, change.value]);
+    }
+
+    return ret;
+  }
+
+  function convertChangesToXML(changes) {
+    var ret = [];
+
+    for (var i = 0; i < changes.length; i++) {
+      var change = changes[i];
+
+      if (change.added) {
+        ret.push('');
+      } else if (change.removed) {
+        ret.push('');
+      }
+
+      ret.push(escapeHTML(change.value));
+
+      if (change.added) {
+        ret.push('');
+      } else if (change.removed) {
+        ret.push('');
+      }
+    }
+
+    return ret.join('');
+  }
+
+  function escapeHTML(s) {
+    var n = s;
+    n = n.replace(/&/g, '&');
+    n = n.replace(//g, '>');
+    n = n.replace(/"/g, '"');
+    return n;
+  }
+
+  /* See LICENSE file for terms of use */
+
+  exports.Diff = Diff;
+  exports.diffChars = diffChars;
+  exports.diffWords = diffWords;
+  exports.diffWordsWithSpace = diffWordsWithSpace;
+  exports.diffLines = diffLines;
+  exports.diffTrimmedLines = diffTrimmedLines;
+  exports.diffSentences = diffSentences;
+  exports.diffCss = diffCss;
+  exports.diffJson = diffJson;
+  exports.diffArrays = diffArrays;
+  exports.structuredPatch = structuredPatch;
+  exports.createTwoFilesPatch = createTwoFilesPatch;
+  exports.createPatch = createPatch;
+  exports.applyPatch = applyPatch;
+  exports.applyPatches = applyPatches;
+  exports.parsePatch = parsePatch;
+  exports.merge = merge;
+  exports.convertChangesToDMP = convertChangesToDMP;
+  exports.convertChangesToXML = convertChangesToXML;
+  exports.canonicalize = canonicalize;
+
+  Object.defineProperty(exports, '__esModule', { value: true });
+
+}));
diff --git a/node_modules/libtap/node_modules/diff/dist/diff.min.js b/node_modules/libtap/node_modules/diff/dist/diff.min.js
new file mode 100644
index 0000000000000..976ad93643a37
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/dist/diff.min.js
@@ -0,0 +1,38 @@
+/*!
+
+ diff v4.0.1
+
+Software License Agreement (BSD License)
+
+Copyright (c) 2009-2015, Kevin Decker 
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of Kevin Decker nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+@license
+*/
+!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e=e||self).Diff={})}(this,function(e){"use strict";function t(){}function g(e,n,t,r,i){for(var o=0,s=n.length,l=0,a=0;oe.length?t:e}),u.value=e.join(d)}else u.value=e.join(t.slice(l,l+u.count));l+=u.count,u.added||(a+=u.count)}}var c=n[s-1];return 1=c&&h<=r+1)return d([{value:this.join(u),count:u.length}]);function i(){for(var e=-1*p;e<=p;e+=2){var n=void 0,t=v[e-1],r=v[e+1],i=(r?r.newPos:0)-e;t&&(v[e-1]=void 0);var o=t&&t.newPos+1=c&&h<=i+1)return d(g(f,n.components,u,a,f.useLongestToken));v[e]=n}else v[e]=void 0}var l;p++}if(n)!function e(){setTimeout(function(){if(t=v.length-2&&t.length<=p.context){var u=/\n$/.test(c),f=/\n$/.test(h),d=0==t.length&&x.length>a.oldLines;!u&&d&&x.splice(a.oldLines,0,"\\ No newline at end of file"),(u||d)&&f||x.push("\\ No newline at end of file")}m.push(a),y=w=0,x=[]}L+=t.length,S+=t.length}},o=0;oe.length)return!1;for(var t=0;t"):r.removed&&n.push(""),n.push((i=r.value,void 0,i.replace(/&/g,"&").replace(//g,">").replace(/"/g,"""))),r.added?n.push(""):r.removed&&n.push("")}var i;return n.join("")},e.canonicalize=v,Object.defineProperty(e,"__esModule",{value:!0})});
\ No newline at end of file
diff --git a/node_modules/libtap/node_modules/diff/lib/convert/dmp.js b/node_modules/libtap/node_modules/diff/lib/convert/dmp.js
new file mode 100644
index 0000000000000..91ff40a9120f7
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/convert/dmp.js
@@ -0,0 +1,32 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.convertChangesToDMP = convertChangesToDMP;
+
+/*istanbul ignore end*/
+// See: http://code.google.com/p/google-diff-match-patch/wiki/API
+function convertChangesToDMP(changes) {
+  var ret = [],
+      change,
+      operation;
+
+  for (var i = 0; i < changes.length; i++) {
+    change = changes[i];
+
+    if (change.added) {
+      operation = 1;
+    } else if (change.removed) {
+      operation = -1;
+    } else {
+      operation = 0;
+    }
+
+    ret.push([operation, change.value]);
+  }
+
+  return ret;
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb252ZXJ0L2RtcC5qcyJdLCJuYW1lcyI6WyJjb252ZXJ0Q2hhbmdlc1RvRE1QIiwiY2hhbmdlcyIsInJldCIsImNoYW5nZSIsIm9wZXJhdGlvbiIsImkiLCJsZW5ndGgiLCJhZGRlZCIsInJlbW92ZWQiLCJwdXNoIiwidmFsdWUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBO0FBQ08sU0FBU0EsbUJBQVQsQ0FBNkJDLE9BQTdCLEVBQXNDO0FBQzNDLE1BQUlDLEdBQUcsR0FBRyxFQUFWO0FBQUEsTUFDSUMsTUFESjtBQUFBLE1BRUlDLFNBRko7O0FBR0EsT0FBSyxJQUFJQyxDQUFDLEdBQUcsQ0FBYixFQUFnQkEsQ0FBQyxHQUFHSixPQUFPLENBQUNLLE1BQTVCLEVBQW9DRCxDQUFDLEVBQXJDLEVBQXlDO0FBQ3ZDRixJQUFBQSxNQUFNLEdBQUdGLE9BQU8sQ0FBQ0ksQ0FBRCxDQUFoQjs7QUFDQSxRQUFJRixNQUFNLENBQUNJLEtBQVgsRUFBa0I7QUFDaEJILE1BQUFBLFNBQVMsR0FBRyxDQUFaO0FBQ0QsS0FGRCxNQUVPLElBQUlELE1BQU0sQ0FBQ0ssT0FBWCxFQUFvQjtBQUN6QkosTUFBQUEsU0FBUyxHQUFHLENBQUMsQ0FBYjtBQUNELEtBRk0sTUFFQTtBQUNMQSxNQUFBQSxTQUFTLEdBQUcsQ0FBWjtBQUNEOztBQUVERixJQUFBQSxHQUFHLENBQUNPLElBQUosQ0FBUyxDQUFDTCxTQUFELEVBQVlELE1BQU0sQ0FBQ08sS0FBbkIsQ0FBVDtBQUNEOztBQUNELFNBQU9SLEdBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbIi8vIFNlZTogaHR0cDovL2NvZGUuZ29vZ2xlLmNvbS9wL2dvb2dsZS1kaWZmLW1hdGNoLXBhdGNoL3dpa2kvQVBJXG5leHBvcnQgZnVuY3Rpb24gY29udmVydENoYW5nZXNUb0RNUChjaGFuZ2VzKSB7XG4gIGxldCByZXQgPSBbXSxcbiAgICAgIGNoYW5nZSxcbiAgICAgIG9wZXJhdGlvbjtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgY2hhbmdlID0gY2hhbmdlc1tpXTtcbiAgICBpZiAoY2hhbmdlLmFkZGVkKSB7XG4gICAgICBvcGVyYXRpb24gPSAxO1xuICAgIH0gZWxzZSBpZiAoY2hhbmdlLnJlbW92ZWQpIHtcbiAgICAgIG9wZXJhdGlvbiA9IC0xO1xuICAgIH0gZWxzZSB7XG4gICAgICBvcGVyYXRpb24gPSAwO1xuICAgIH1cblxuICAgIHJldC5wdXNoKFtvcGVyYXRpb24sIGNoYW5nZS52YWx1ZV0pO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG4iXX0=
diff --git a/node_modules/libtap/node_modules/diff/lib/convert/xml.js b/node_modules/libtap/node_modules/diff/lib/convert/xml.js
new file mode 100644
index 0000000000000..69ec60c66c81d
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/convert/xml.js
@@ -0,0 +1,42 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.convertChangesToXML = convertChangesToXML;
+
+/*istanbul ignore end*/
+function convertChangesToXML(changes) {
+  var ret = [];
+
+  for (var i = 0; i < changes.length; i++) {
+    var change = changes[i];
+
+    if (change.added) {
+      ret.push('');
+    } else if (change.removed) {
+      ret.push('');
+    }
+
+    ret.push(escapeHTML(change.value));
+
+    if (change.added) {
+      ret.push('');
+    } else if (change.removed) {
+      ret.push('');
+    }
+  }
+
+  return ret.join('');
+}
+
+function escapeHTML(s) {
+  var n = s;
+  n = n.replace(/&/g, '&');
+  n = n.replace(//g, '>');
+  n = n.replace(/"/g, '"');
+  return n;
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb252ZXJ0L3htbC5qcyJdLCJuYW1lcyI6WyJjb252ZXJ0Q2hhbmdlc1RvWE1MIiwiY2hhbmdlcyIsInJldCIsImkiLCJsZW5ndGgiLCJjaGFuZ2UiLCJhZGRlZCIsInB1c2giLCJyZW1vdmVkIiwiZXNjYXBlSFRNTCIsInZhbHVlIiwiam9pbiIsInMiLCJuIiwicmVwbGFjZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQU8sU0FBU0EsbUJBQVQsQ0FBNkJDLE9BQTdCLEVBQXNDO0FBQzNDLE1BQUlDLEdBQUcsR0FBRyxFQUFWOztBQUNBLE9BQUssSUFBSUMsQ0FBQyxHQUFHLENBQWIsRUFBZ0JBLENBQUMsR0FBR0YsT0FBTyxDQUFDRyxNQUE1QixFQUFvQ0QsQ0FBQyxFQUFyQyxFQUF5QztBQUN2QyxRQUFJRSxNQUFNLEdBQUdKLE9BQU8sQ0FBQ0UsQ0FBRCxDQUFwQjs7QUFDQSxRQUFJRSxNQUFNLENBQUNDLEtBQVgsRUFBa0I7QUFDaEJKLE1BQUFBLEdBQUcsQ0FBQ0ssSUFBSixDQUFTLE9BQVQ7QUFDRCxLQUZELE1BRU8sSUFBSUYsTUFBTSxDQUFDRyxPQUFYLEVBQW9CO0FBQ3pCTixNQUFBQSxHQUFHLENBQUNLLElBQUosQ0FBUyxPQUFUO0FBQ0Q7O0FBRURMLElBQUFBLEdBQUcsQ0FBQ0ssSUFBSixDQUFTRSxVQUFVLENBQUNKLE1BQU0sQ0FBQ0ssS0FBUixDQUFuQjs7QUFFQSxRQUFJTCxNQUFNLENBQUNDLEtBQVgsRUFBa0I7QUFDaEJKLE1BQUFBLEdBQUcsQ0FBQ0ssSUFBSixDQUFTLFFBQVQ7QUFDRCxLQUZELE1BRU8sSUFBSUYsTUFBTSxDQUFDRyxPQUFYLEVBQW9CO0FBQ3pCTixNQUFBQSxHQUFHLENBQUNLLElBQUosQ0FBUyxRQUFUO0FBQ0Q7QUFDRjs7QUFDRCxTQUFPTCxHQUFHLENBQUNTLElBQUosQ0FBUyxFQUFULENBQVA7QUFDRDs7QUFFRCxTQUFTRixVQUFULENBQW9CRyxDQUFwQixFQUF1QjtBQUNyQixNQUFJQyxDQUFDLEdBQUdELENBQVI7QUFDQUMsRUFBQUEsQ0FBQyxHQUFHQSxDQUFDLENBQUNDLE9BQUYsQ0FBVSxJQUFWLEVBQWdCLE9BQWhCLENBQUo7QUFDQUQsRUFBQUEsQ0FBQyxHQUFHQSxDQUFDLENBQUNDLE9BQUYsQ0FBVSxJQUFWLEVBQWdCLE1BQWhCLENBQUo7QUFDQUQsRUFBQUEsQ0FBQyxHQUFHQSxDQUFDLENBQUNDLE9BQUYsQ0FBVSxJQUFWLEVBQWdCLE1BQWhCLENBQUo7QUFDQUQsRUFBQUEsQ0FBQyxHQUFHQSxDQUFDLENBQUNDLE9BQUYsQ0FBVSxJQUFWLEVBQWdCLFFBQWhCLENBQUo7QUFFQSxTQUFPRCxDQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gY29udmVydENoYW5nZXNUb1hNTChjaGFuZ2VzKSB7XG4gIGxldCByZXQgPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGNoYW5nZSA9IGNoYW5nZXNbaV07XG4gICAgaWYgKGNoYW5nZS5hZGRlZCkge1xuICAgICAgcmV0LnB1c2goJzxpbnM+Jyk7XG4gICAgfSBlbHNlIGlmIChjaGFuZ2UucmVtb3ZlZCkge1xuICAgICAgcmV0LnB1c2goJzxkZWw+Jyk7XG4gICAgfVxuXG4gICAgcmV0LnB1c2goZXNjYXBlSFRNTChjaGFuZ2UudmFsdWUpKTtcblxuICAgIGlmIChjaGFuZ2UuYWRkZWQpIHtcbiAgICAgIHJldC5wdXNoKCc8L2lucz4nKTtcbiAgICB9IGVsc2UgaWYgKGNoYW5nZS5yZW1vdmVkKSB7XG4gICAgICByZXQucHVzaCgnPC9kZWw+Jyk7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXQuam9pbignJyk7XG59XG5cbmZ1bmN0aW9uIGVzY2FwZUhUTUwocykge1xuICBsZXQgbiA9IHM7XG4gIG4gPSBuLnJlcGxhY2UoLyYvZywgJyZhbXA7Jyk7XG4gIG4gPSBuLnJlcGxhY2UoLzwvZywgJyZsdDsnKTtcbiAgbiA9IG4ucmVwbGFjZSgvPi9nLCAnJmd0OycpO1xuICBuID0gbi5yZXBsYWNlKC9cIi9nLCAnJnF1b3Q7Jyk7XG5cbiAgcmV0dXJuIG47XG59XG4iXX0=
diff --git a/node_modules/libtap/node_modules/diff/lib/diff/array.js b/node_modules/libtap/node_modules/diff/lib/diff/array.js
new file mode 100644
index 0000000000000..81f42ea4d9b95
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/diff/array.js
@@ -0,0 +1,45 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.diffArrays = diffArrays;
+exports.arrayDiff = void 0;
+
+/*istanbul ignore end*/
+var
+/*istanbul ignore start*/
+_base = _interopRequireDefault(require("./base"))
+/*istanbul ignore end*/
+;
+
+/*istanbul ignore start*/ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/*istanbul ignore end*/
+var arrayDiff = new
+/*istanbul ignore start*/
+_base
+/*istanbul ignore end*/
+.
+/*istanbul ignore start*/
+default
+/*istanbul ignore end*/
+();
+
+/*istanbul ignore start*/
+exports.arrayDiff = arrayDiff;
+
+/*istanbul ignore end*/
+arrayDiff.tokenize = function (value) {
+  return value.slice();
+};
+
+arrayDiff.join = arrayDiff.removeEmpty = function (value) {
+  return value;
+};
+
+function diffArrays(oldArr, newArr, callback) {
+  return arrayDiff.diff(oldArr, newArr, callback);
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2FycmF5LmpzIl0sIm5hbWVzIjpbImFycmF5RGlmZiIsIkRpZmYiLCJ0b2tlbml6ZSIsInZhbHVlIiwic2xpY2UiLCJqb2luIiwicmVtb3ZlRW1wdHkiLCJkaWZmQXJyYXlzIiwib2xkQXJyIiwibmV3QXJyIiwiY2FsbGJhY2siLCJkaWZmIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7Ozs7QUFFTyxJQUFNQSxTQUFTLEdBQUc7QUFBSUM7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBSjtBQUFBLEVBQWxCOzs7Ozs7QUFDUEQsU0FBUyxDQUFDRSxRQUFWLEdBQXFCLFVBQVNDLEtBQVQsRUFBZ0I7QUFDbkMsU0FBT0EsS0FBSyxDQUFDQyxLQUFOLEVBQVA7QUFDRCxDQUZEOztBQUdBSixTQUFTLENBQUNLLElBQVYsR0FBaUJMLFNBQVMsQ0FBQ00sV0FBVixHQUF3QixVQUFTSCxLQUFULEVBQWdCO0FBQ3ZELFNBQU9BLEtBQVA7QUFDRCxDQUZEOztBQUlPLFNBQVNJLFVBQVQsQ0FBb0JDLE1BQXBCLEVBQTRCQyxNQUE1QixFQUFvQ0MsUUFBcEMsRUFBOEM7QUFBRSxTQUFPVixTQUFTLENBQUNXLElBQVYsQ0FBZUgsTUFBZixFQUF1QkMsTUFBdkIsRUFBK0JDLFFBQS9CLENBQVA7QUFBa0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRGlmZiBmcm9tICcuL2Jhc2UnO1xuXG5leHBvcnQgY29uc3QgYXJyYXlEaWZmID0gbmV3IERpZmYoKTtcbmFycmF5RGlmZi50b2tlbml6ZSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZS5zbGljZSgpO1xufTtcbmFycmF5RGlmZi5qb2luID0gYXJyYXlEaWZmLnJlbW92ZUVtcHR5ID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGRpZmZBcnJheXMob2xkQXJyLCBuZXdBcnIsIGNhbGxiYWNrKSB7IHJldHVybiBhcnJheURpZmYuZGlmZihvbGRBcnIsIG5ld0FyciwgY2FsbGJhY2spOyB9XG4iXX0=
diff --git a/node_modules/libtap/node_modules/diff/lib/diff/base.js b/node_modules/libtap/node_modules/diff/lib/diff/base.js
new file mode 100644
index 0000000000000..ea661fe3eb6f7
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/diff/base.js
@@ -0,0 +1,304 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = Diff;
+
+/*istanbul ignore end*/
+function Diff() {}
+
+Diff.prototype = {
+  /*istanbul ignore start*/
+
+  /*istanbul ignore end*/
+  diff: function diff(oldString, newString) {
+    /*istanbul ignore start*/
+    var
+    /*istanbul ignore end*/
+    options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
+    var callback = options.callback;
+
+    if (typeof options === 'function') {
+      callback = options;
+      options = {};
+    }
+
+    this.options = options;
+    var self = this;
+
+    function done(value) {
+      if (callback) {
+        setTimeout(function () {
+          callback(undefined, value);
+        }, 0);
+        return true;
+      } else {
+        return value;
+      }
+    } // Allow subclasses to massage the input prior to running
+
+
+    oldString = this.castInput(oldString);
+    newString = this.castInput(newString);
+    oldString = this.removeEmpty(this.tokenize(oldString));
+    newString = this.removeEmpty(this.tokenize(newString));
+    var newLen = newString.length,
+        oldLen = oldString.length;
+    var editLength = 1;
+    var maxEditLength = newLen + oldLen;
+    var bestPath = [{
+      newPos: -1,
+      components: []
+    }]; // Seed editLength = 0, i.e. the content starts with the same values
+
+    var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
+
+    if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
+      // Identity per the equality and tokenizer
+      return done([{
+        value: this.join(newString),
+        count: newString.length
+      }]);
+    } // Main worker method. checks all permutations of a given edit length for acceptance.
+
+
+    function execEditLength() {
+      for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) {
+        var basePath =
+        /*istanbul ignore start*/
+        void 0
+        /*istanbul ignore end*/
+        ;
+
+        var addPath = bestPath[diagonalPath - 1],
+            removePath = bestPath[diagonalPath + 1],
+            _oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
+
+        if (addPath) {
+          // No one else is going to attempt to use this value, clear it
+          bestPath[diagonalPath - 1] = undefined;
+        }
+
+        var canAdd = addPath && addPath.newPos + 1 < newLen,
+            canRemove = removePath && 0 <= _oldPos && _oldPos < oldLen;
+
+        if (!canAdd && !canRemove) {
+          // If this path is a terminal then prune
+          bestPath[diagonalPath] = undefined;
+          continue;
+        } // Select the diagonal that we want to branch from. We select the prior
+        // path whose position in the new string is the farthest from the origin
+        // and does not pass the bounds of the diff graph
+
+
+        if (!canAdd || canRemove && addPath.newPos < removePath.newPos) {
+          basePath = clonePath(removePath);
+          self.pushComponent(basePath.components, undefined, true);
+        } else {
+          basePath = addPath; // No need to clone, we've pulled it from the list
+
+          basePath.newPos++;
+          self.pushComponent(basePath.components, true, undefined);
+        }
+
+        _oldPos = self.extractCommon(basePath, newString, oldString, diagonalPath); // If we have hit the end of both strings, then we are done
+
+        if (basePath.newPos + 1 >= newLen && _oldPos + 1 >= oldLen) {
+          return done(buildValues(self, basePath.components, newString, oldString, self.useLongestToken));
+        } else {
+          // Otherwise track this path as a potential candidate and continue.
+          bestPath[diagonalPath] = basePath;
+        }
+      }
+
+      editLength++;
+    } // Performs the length of edit iteration. Is a bit fugly as this has to support the
+    // sync and async mode which is never fun. Loops over execEditLength until a value
+    // is produced.
+
+
+    if (callback) {
+      (function exec() {
+        setTimeout(function () {
+          // This should not happen, but we want to be safe.
+
+          /* istanbul ignore next */
+          if (editLength > maxEditLength) {
+            return callback();
+          }
+
+          if (!execEditLength()) {
+            exec();
+          }
+        }, 0);
+      })();
+    } else {
+      while (editLength <= maxEditLength) {
+        var ret = execEditLength();
+
+        if (ret) {
+          return ret;
+        }
+      }
+    }
+  },
+
+  /*istanbul ignore start*/
+
+  /*istanbul ignore end*/
+  pushComponent: function pushComponent(components, added, removed) {
+    var last = components[components.length - 1];
+
+    if (last && last.added === added && last.removed === removed) {
+      // We need to clone here as the component clone operation is just
+      // as shallow array clone
+      components[components.length - 1] = {
+        count: last.count + 1,
+        added: added,
+        removed: removed
+      };
+    } else {
+      components.push({
+        count: 1,
+        added: added,
+        removed: removed
+      });
+    }
+  },
+
+  /*istanbul ignore start*/
+
+  /*istanbul ignore end*/
+  extractCommon: function extractCommon(basePath, newString, oldString, diagonalPath) {
+    var newLen = newString.length,
+        oldLen = oldString.length,
+        newPos = basePath.newPos,
+        oldPos = newPos - diagonalPath,
+        commonCount = 0;
+
+    while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) {
+      newPos++;
+      oldPos++;
+      commonCount++;
+    }
+
+    if (commonCount) {
+      basePath.components.push({
+        count: commonCount
+      });
+    }
+
+    basePath.newPos = newPos;
+    return oldPos;
+  },
+
+  /*istanbul ignore start*/
+
+  /*istanbul ignore end*/
+  equals: function equals(left, right) {
+    if (this.options.comparator) {
+      return this.options.comparator(left, right);
+    } else {
+      return left === right || this.options.ignoreCase && left.toLowerCase() === right.toLowerCase();
+    }
+  },
+
+  /*istanbul ignore start*/
+
+  /*istanbul ignore end*/
+  removeEmpty: function removeEmpty(array) {
+    var ret = [];
+
+    for (var i = 0; i < array.length; i++) {
+      if (array[i]) {
+        ret.push(array[i]);
+      }
+    }
+
+    return ret;
+  },
+
+  /*istanbul ignore start*/
+
+  /*istanbul ignore end*/
+  castInput: function castInput(value) {
+    return value;
+  },
+
+  /*istanbul ignore start*/
+
+  /*istanbul ignore end*/
+  tokenize: function tokenize(value) {
+    return value.split('');
+  },
+
+  /*istanbul ignore start*/
+
+  /*istanbul ignore end*/
+  join: function join(chars) {
+    return chars.join('');
+  }
+};
+
+function buildValues(diff, components, newString, oldString, useLongestToken) {
+  var componentPos = 0,
+      componentLen = components.length,
+      newPos = 0,
+      oldPos = 0;
+
+  for (; componentPos < componentLen; componentPos++) {
+    var component = components[componentPos];
+
+    if (!component.removed) {
+      if (!component.added && useLongestToken) {
+        var value = newString.slice(newPos, newPos + component.count);
+        value = value.map(function (value, i) {
+          var oldValue = oldString[oldPos + i];
+          return oldValue.length > value.length ? oldValue : value;
+        });
+        component.value = diff.join(value);
+      } else {
+        component.value = diff.join(newString.slice(newPos, newPos + component.count));
+      }
+
+      newPos += component.count; // Common case
+
+      if (!component.added) {
+        oldPos += component.count;
+      }
+    } else {
+      component.value = diff.join(oldString.slice(oldPos, oldPos + component.count));
+      oldPos += component.count; // Reverse add and remove so removes are output first to match common convention
+      // The diffing algorithm is tied to add then remove output and this is the simplest
+      // route to get the desired output with minimal overhead.
+
+      if (componentPos && components[componentPos - 1].added) {
+        var tmp = components[componentPos - 1];
+        components[componentPos - 1] = components[componentPos];
+        components[componentPos] = tmp;
+      }
+    }
+  } // Special case handle for when one terminal is ignored (i.e. whitespace).
+  // For this case we merge the terminal into the prior string and drop the change.
+  // This is only available for string mode.
+
+
+  var lastComponent = components[componentLen - 1];
+
+  if (componentLen > 1 && typeof lastComponent.value === 'string' && (lastComponent.added || lastComponent.removed) && diff.equals('', lastComponent.value)) {
+    components[componentLen - 2].value += lastComponent.value;
+    components.pop();
+  }
+
+  return components;
+}
+
+function clonePath(path) {
+  return {
+    newPos: path.newPos,
+    components: path.components.slice(0)
+  };
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2Jhc2UuanMiXSwibmFtZXMiOlsiRGlmZiIsInByb3RvdHlwZSIsImRpZmYiLCJvbGRTdHJpbmciLCJuZXdTdHJpbmciLCJvcHRpb25zIiwiY2FsbGJhY2siLCJzZWxmIiwiZG9uZSIsInZhbHVlIiwic2V0VGltZW91dCIsInVuZGVmaW5lZCIsImNhc3RJbnB1dCIsInJlbW92ZUVtcHR5IiwidG9rZW5pemUiLCJuZXdMZW4iLCJsZW5ndGgiLCJvbGRMZW4iLCJlZGl0TGVuZ3RoIiwibWF4RWRpdExlbmd0aCIsImJlc3RQYXRoIiwibmV3UG9zIiwiY29tcG9uZW50cyIsIm9sZFBvcyIsImV4dHJhY3RDb21tb24iLCJqb2luIiwiY291bnQiLCJleGVjRWRpdExlbmd0aCIsImRpYWdvbmFsUGF0aCIsImJhc2VQYXRoIiwiYWRkUGF0aCIsInJlbW92ZVBhdGgiLCJjYW5BZGQiLCJjYW5SZW1vdmUiLCJjbG9uZVBhdGgiLCJwdXNoQ29tcG9uZW50IiwiYnVpbGRWYWx1ZXMiLCJ1c2VMb25nZXN0VG9rZW4iLCJleGVjIiwicmV0IiwiYWRkZWQiLCJyZW1vdmVkIiwibGFzdCIsInB1c2giLCJjb21tb25Db3VudCIsImVxdWFscyIsImxlZnQiLCJyaWdodCIsImNvbXBhcmF0b3IiLCJpZ25vcmVDYXNlIiwidG9Mb3dlckNhc2UiLCJhcnJheSIsImkiLCJzcGxpdCIsImNoYXJzIiwiY29tcG9uZW50UG9zIiwiY29tcG9uZW50TGVuIiwiY29tcG9uZW50Iiwic2xpY2UiLCJtYXAiLCJvbGRWYWx1ZSIsInRtcCIsImxhc3RDb21wb25lbnQiLCJwb3AiLCJwYXRoIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBZSxTQUFTQSxJQUFULEdBQWdCLENBQUU7O0FBRWpDQSxJQUFJLENBQUNDLFNBQUwsR0FBaUI7QUFBQTs7QUFBQTtBQUNmQyxFQUFBQSxJQURlLGdCQUNWQyxTQURVLEVBQ0NDLFNBREQsRUFDMEI7QUFBQTtBQUFBO0FBQUE7QUFBZEMsSUFBQUEsT0FBYyx1RUFBSixFQUFJO0FBQ3ZDLFFBQUlDLFFBQVEsR0FBR0QsT0FBTyxDQUFDQyxRQUF2Qjs7QUFDQSxRQUFJLE9BQU9ELE9BQVAsS0FBbUIsVUFBdkIsRUFBbUM7QUFDakNDLE1BQUFBLFFBQVEsR0FBR0QsT0FBWDtBQUNBQSxNQUFBQSxPQUFPLEdBQUcsRUFBVjtBQUNEOztBQUNELFNBQUtBLE9BQUwsR0FBZUEsT0FBZjtBQUVBLFFBQUlFLElBQUksR0FBRyxJQUFYOztBQUVBLGFBQVNDLElBQVQsQ0FBY0MsS0FBZCxFQUFxQjtBQUNuQixVQUFJSCxRQUFKLEVBQWM7QUFDWkksUUFBQUEsVUFBVSxDQUFDLFlBQVc7QUFBRUosVUFBQUEsUUFBUSxDQUFDSyxTQUFELEVBQVlGLEtBQVosQ0FBUjtBQUE2QixTQUEzQyxFQUE2QyxDQUE3QyxDQUFWO0FBQ0EsZUFBTyxJQUFQO0FBQ0QsT0FIRCxNQUdPO0FBQ0wsZUFBT0EsS0FBUDtBQUNEO0FBQ0YsS0FqQnNDLENBbUJ2Qzs7O0FBQ0FOLElBQUFBLFNBQVMsR0FBRyxLQUFLUyxTQUFMLENBQWVULFNBQWYsQ0FBWjtBQUNBQyxJQUFBQSxTQUFTLEdBQUcsS0FBS1EsU0FBTCxDQUFlUixTQUFmLENBQVo7QUFFQUQsSUFBQUEsU0FBUyxHQUFHLEtBQUtVLFdBQUwsQ0FBaUIsS0FBS0MsUUFBTCxDQUFjWCxTQUFkLENBQWpCLENBQVo7QUFDQUMsSUFBQUEsU0FBUyxHQUFHLEtBQUtTLFdBQUwsQ0FBaUIsS0FBS0MsUUFBTCxDQUFjVixTQUFkLENBQWpCLENBQVo7QUFFQSxRQUFJVyxNQUFNLEdBQUdYLFNBQVMsQ0FBQ1ksTUFBdkI7QUFBQSxRQUErQkMsTUFBTSxHQUFHZCxTQUFTLENBQUNhLE1BQWxEO0FBQ0EsUUFBSUUsVUFBVSxHQUFHLENBQWpCO0FBQ0EsUUFBSUMsYUFBYSxHQUFHSixNQUFNLEdBQUdFLE1BQTdCO0FBQ0EsUUFBSUcsUUFBUSxHQUFHLENBQUM7QUFBRUMsTUFBQUEsTUFBTSxFQUFFLENBQUMsQ0FBWDtBQUFjQyxNQUFBQSxVQUFVLEVBQUU7QUFBMUIsS0FBRCxDQUFmLENBN0J1QyxDQStCdkM7O0FBQ0EsUUFBSUMsTUFBTSxHQUFHLEtBQUtDLGFBQUwsQ0FBbUJKLFFBQVEsQ0FBQyxDQUFELENBQTNCLEVBQWdDaEIsU0FBaEMsRUFBMkNELFNBQTNDLEVBQXNELENBQXRELENBQWI7O0FBQ0EsUUFBSWlCLFFBQVEsQ0FBQyxDQUFELENBQVIsQ0FBWUMsTUFBWixHQUFxQixDQUFyQixJQUEwQk4sTUFBMUIsSUFBb0NRLE1BQU0sR0FBRyxDQUFULElBQWNOLE1BQXRELEVBQThEO0FBQzVEO0FBQ0EsYUFBT1QsSUFBSSxDQUFDLENBQUM7QUFBQ0MsUUFBQUEsS0FBSyxFQUFFLEtBQUtnQixJQUFMLENBQVVyQixTQUFWLENBQVI7QUFBOEJzQixRQUFBQSxLQUFLLEVBQUV0QixTQUFTLENBQUNZO0FBQS9DLE9BQUQsQ0FBRCxDQUFYO0FBQ0QsS0FwQ3NDLENBc0N2Qzs7O0FBQ0EsYUFBU1csY0FBVCxHQUEwQjtBQUN4QixXQUFLLElBQUlDLFlBQVksR0FBRyxDQUFDLENBQUQsR0FBS1YsVUFBN0IsRUFBeUNVLFlBQVksSUFBSVYsVUFBekQsRUFBcUVVLFlBQVksSUFBSSxDQUFyRixFQUF3RjtBQUN0RixZQUFJQyxRQUFRO0FBQUE7QUFBQTtBQUFaO0FBQUE7O0FBQ0EsWUFBSUMsT0FBTyxHQUFHVixRQUFRLENBQUNRLFlBQVksR0FBRyxDQUFoQixDQUF0QjtBQUFBLFlBQ0lHLFVBQVUsR0FBR1gsUUFBUSxDQUFDUSxZQUFZLEdBQUcsQ0FBaEIsQ0FEekI7QUFBQSxZQUVJTCxPQUFNLEdBQUcsQ0FBQ1EsVUFBVSxHQUFHQSxVQUFVLENBQUNWLE1BQWQsR0FBdUIsQ0FBbEMsSUFBdUNPLFlBRnBEOztBQUdBLFlBQUlFLE9BQUosRUFBYTtBQUNYO0FBQ0FWLFVBQUFBLFFBQVEsQ0FBQ1EsWUFBWSxHQUFHLENBQWhCLENBQVIsR0FBNkJqQixTQUE3QjtBQUNEOztBQUVELFlBQUlxQixNQUFNLEdBQUdGLE9BQU8sSUFBSUEsT0FBTyxDQUFDVCxNQUFSLEdBQWlCLENBQWpCLEdBQXFCTixNQUE3QztBQUFBLFlBQ0lrQixTQUFTLEdBQUdGLFVBQVUsSUFBSSxLQUFLUixPQUFuQixJQUE2QkEsT0FBTSxHQUFHTixNQUR0RDs7QUFFQSxZQUFJLENBQUNlLE1BQUQsSUFBVyxDQUFDQyxTQUFoQixFQUEyQjtBQUN6QjtBQUNBYixVQUFBQSxRQUFRLENBQUNRLFlBQUQsQ0FBUixHQUF5QmpCLFNBQXpCO0FBQ0E7QUFDRCxTQWhCcUYsQ0FrQnRGO0FBQ0E7QUFDQTs7O0FBQ0EsWUFBSSxDQUFDcUIsTUFBRCxJQUFZQyxTQUFTLElBQUlILE9BQU8sQ0FBQ1QsTUFBUixHQUFpQlUsVUFBVSxDQUFDVixNQUF6RCxFQUFrRTtBQUNoRVEsVUFBQUEsUUFBUSxHQUFHSyxTQUFTLENBQUNILFVBQUQsQ0FBcEI7QUFDQXhCLFVBQUFBLElBQUksQ0FBQzRCLGFBQUwsQ0FBbUJOLFFBQVEsQ0FBQ1AsVUFBNUIsRUFBd0NYLFNBQXhDLEVBQW1ELElBQW5EO0FBQ0QsU0FIRCxNQUdPO0FBQ0xrQixVQUFBQSxRQUFRLEdBQUdDLE9BQVgsQ0FESyxDQUNlOztBQUNwQkQsVUFBQUEsUUFBUSxDQUFDUixNQUFUO0FBQ0FkLFVBQUFBLElBQUksQ0FBQzRCLGFBQUwsQ0FBbUJOLFFBQVEsQ0FBQ1AsVUFBNUIsRUFBd0MsSUFBeEMsRUFBOENYLFNBQTlDO0FBQ0Q7O0FBRURZLFFBQUFBLE9BQU0sR0FBR2hCLElBQUksQ0FBQ2lCLGFBQUwsQ0FBbUJLLFFBQW5CLEVBQTZCekIsU0FBN0IsRUFBd0NELFNBQXhDLEVBQW1EeUIsWUFBbkQsQ0FBVCxDQTlCc0YsQ0FnQ3RGOztBQUNBLFlBQUlDLFFBQVEsQ0FBQ1IsTUFBVCxHQUFrQixDQUFsQixJQUF1Qk4sTUFBdkIsSUFBaUNRLE9BQU0sR0FBRyxDQUFULElBQWNOLE1BQW5ELEVBQTJEO0FBQ3pELGlCQUFPVCxJQUFJLENBQUM0QixXQUFXLENBQUM3QixJQUFELEVBQU9zQixRQUFRLENBQUNQLFVBQWhCLEVBQTRCbEIsU0FBNUIsRUFBdUNELFNBQXZDLEVBQWtESSxJQUFJLENBQUM4QixlQUF2RCxDQUFaLENBQVg7QUFDRCxTQUZELE1BRU87QUFDTDtBQUNBakIsVUFBQUEsUUFBUSxDQUFDUSxZQUFELENBQVIsR0FBeUJDLFFBQXpCO0FBQ0Q7QUFDRjs7QUFFRFgsTUFBQUEsVUFBVTtBQUNYLEtBbEZzQyxDQW9GdkM7QUFDQTtBQUNBOzs7QUFDQSxRQUFJWixRQUFKLEVBQWM7QUFDWCxnQkFBU2dDLElBQVQsR0FBZ0I7QUFDZjVCLFFBQUFBLFVBQVUsQ0FBQyxZQUFXO0FBQ3BCOztBQUNBO0FBQ0EsY0FBSVEsVUFBVSxHQUFHQyxhQUFqQixFQUFnQztBQUM5QixtQkFBT2IsUUFBUSxFQUFmO0FBQ0Q7O0FBRUQsY0FBSSxDQUFDcUIsY0FBYyxFQUFuQixFQUF1QjtBQUNyQlcsWUFBQUEsSUFBSTtBQUNMO0FBQ0YsU0FWUyxFQVVQLENBVk8sQ0FBVjtBQVdELE9BWkEsR0FBRDtBQWFELEtBZEQsTUFjTztBQUNMLGFBQU9wQixVQUFVLElBQUlDLGFBQXJCLEVBQW9DO0FBQ2xDLFlBQUlvQixHQUFHLEdBQUdaLGNBQWMsRUFBeEI7O0FBQ0EsWUFBSVksR0FBSixFQUFTO0FBQ1AsaUJBQU9BLEdBQVA7QUFDRDtBQUNGO0FBQ0Y7QUFDRixHQTlHYzs7QUFBQTs7QUFBQTtBQWdIZkosRUFBQUEsYUFoSGUseUJBZ0hEYixVQWhIQyxFQWdIV2tCLEtBaEhYLEVBZ0hrQkMsT0FoSGxCLEVBZ0gyQjtBQUN4QyxRQUFJQyxJQUFJLEdBQUdwQixVQUFVLENBQUNBLFVBQVUsQ0FBQ04sTUFBWCxHQUFvQixDQUFyQixDQUFyQjs7QUFDQSxRQUFJMEIsSUFBSSxJQUFJQSxJQUFJLENBQUNGLEtBQUwsS0FBZUEsS0FBdkIsSUFBZ0NFLElBQUksQ0FBQ0QsT0FBTCxLQUFpQkEsT0FBckQsRUFBOEQ7QUFDNUQ7QUFDQTtBQUNBbkIsTUFBQUEsVUFBVSxDQUFDQSxVQUFVLENBQUNOLE1BQVgsR0FBb0IsQ0FBckIsQ0FBVixHQUFvQztBQUFDVSxRQUFBQSxLQUFLLEVBQUVnQixJQUFJLENBQUNoQixLQUFMLEdBQWEsQ0FBckI7QUFBd0JjLFFBQUFBLEtBQUssRUFBRUEsS0FBL0I7QUFBc0NDLFFBQUFBLE9BQU8sRUFBRUE7QUFBL0MsT0FBcEM7QUFDRCxLQUpELE1BSU87QUFDTG5CLE1BQUFBLFVBQVUsQ0FBQ3FCLElBQVgsQ0FBZ0I7QUFBQ2pCLFFBQUFBLEtBQUssRUFBRSxDQUFSO0FBQVdjLFFBQUFBLEtBQUssRUFBRUEsS0FBbEI7QUFBeUJDLFFBQUFBLE9BQU8sRUFBRUE7QUFBbEMsT0FBaEI7QUFDRDtBQUNGLEdBekhjOztBQUFBOztBQUFBO0FBMEhmakIsRUFBQUEsYUExSGUseUJBMEhESyxRQTFIQyxFQTBIU3pCLFNBMUhULEVBMEhvQkQsU0ExSHBCLEVBMEgrQnlCLFlBMUgvQixFQTBINkM7QUFDMUQsUUFBSWIsTUFBTSxHQUFHWCxTQUFTLENBQUNZLE1BQXZCO0FBQUEsUUFDSUMsTUFBTSxHQUFHZCxTQUFTLENBQUNhLE1BRHZCO0FBQUEsUUFFSUssTUFBTSxHQUFHUSxRQUFRLENBQUNSLE1BRnRCO0FBQUEsUUFHSUUsTUFBTSxHQUFHRixNQUFNLEdBQUdPLFlBSHRCO0FBQUEsUUFLSWdCLFdBQVcsR0FBRyxDQUxsQjs7QUFNQSxXQUFPdkIsTUFBTSxHQUFHLENBQVQsR0FBYU4sTUFBYixJQUF1QlEsTUFBTSxHQUFHLENBQVQsR0FBYU4sTUFBcEMsSUFBOEMsS0FBSzRCLE1BQUwsQ0FBWXpDLFNBQVMsQ0FBQ2lCLE1BQU0sR0FBRyxDQUFWLENBQXJCLEVBQW1DbEIsU0FBUyxDQUFDb0IsTUFBTSxHQUFHLENBQVYsQ0FBNUMsQ0FBckQsRUFBZ0g7QUFDOUdGLE1BQUFBLE1BQU07QUFDTkUsTUFBQUEsTUFBTTtBQUNOcUIsTUFBQUEsV0FBVztBQUNaOztBQUVELFFBQUlBLFdBQUosRUFBaUI7QUFDZmYsTUFBQUEsUUFBUSxDQUFDUCxVQUFULENBQW9CcUIsSUFBcEIsQ0FBeUI7QUFBQ2pCLFFBQUFBLEtBQUssRUFBRWtCO0FBQVIsT0FBekI7QUFDRDs7QUFFRGYsSUFBQUEsUUFBUSxDQUFDUixNQUFULEdBQWtCQSxNQUFsQjtBQUNBLFdBQU9FLE1BQVA7QUFDRCxHQTdJYzs7QUFBQTs7QUFBQTtBQStJZnNCLEVBQUFBLE1BL0llLGtCQStJUkMsSUEvSVEsRUErSUZDLEtBL0lFLEVBK0lLO0FBQ2xCLFFBQUksS0FBSzFDLE9BQUwsQ0FBYTJDLFVBQWpCLEVBQTZCO0FBQzNCLGFBQU8sS0FBSzNDLE9BQUwsQ0FBYTJDLFVBQWIsQ0FBd0JGLElBQXhCLEVBQThCQyxLQUE5QixDQUFQO0FBQ0QsS0FGRCxNQUVPO0FBQ0wsYUFBT0QsSUFBSSxLQUFLQyxLQUFULElBQ0QsS0FBSzFDLE9BQUwsQ0FBYTRDLFVBQWIsSUFBMkJILElBQUksQ0FBQ0ksV0FBTCxPQUF1QkgsS0FBSyxDQUFDRyxXQUFOLEVBRHhEO0FBRUQ7QUFDRixHQXRKYzs7QUFBQTs7QUFBQTtBQXVKZnJDLEVBQUFBLFdBdkplLHVCQXVKSHNDLEtBdkpHLEVBdUpJO0FBQ2pCLFFBQUlaLEdBQUcsR0FBRyxFQUFWOztBQUNBLFNBQUssSUFBSWEsQ0FBQyxHQUFHLENBQWIsRUFBZ0JBLENBQUMsR0FBR0QsS0FBSyxDQUFDbkMsTUFBMUIsRUFBa0NvQyxDQUFDLEVBQW5DLEVBQXVDO0FBQ3JDLFVBQUlELEtBQUssQ0FBQ0MsQ0FBRCxDQUFULEVBQWM7QUFDWmIsUUFBQUEsR0FBRyxDQUFDSSxJQUFKLENBQVNRLEtBQUssQ0FBQ0MsQ0FBRCxDQUFkO0FBQ0Q7QUFDRjs7QUFDRCxXQUFPYixHQUFQO0FBQ0QsR0EvSmM7O0FBQUE7O0FBQUE7QUFnS2YzQixFQUFBQSxTQWhLZSxxQkFnS0xILEtBaEtLLEVBZ0tFO0FBQ2YsV0FBT0EsS0FBUDtBQUNELEdBbEtjOztBQUFBOztBQUFBO0FBbUtmSyxFQUFBQSxRQW5LZSxvQkFtS05MLEtBbktNLEVBbUtDO0FBQ2QsV0FBT0EsS0FBSyxDQUFDNEMsS0FBTixDQUFZLEVBQVosQ0FBUDtBQUNELEdBcktjOztBQUFBOztBQUFBO0FBc0tmNUIsRUFBQUEsSUF0S2UsZ0JBc0tWNkIsS0F0S1UsRUFzS0g7QUFDVixXQUFPQSxLQUFLLENBQUM3QixJQUFOLENBQVcsRUFBWCxDQUFQO0FBQ0Q7QUF4S2MsQ0FBakI7O0FBMktBLFNBQVNXLFdBQVQsQ0FBcUJsQyxJQUFyQixFQUEyQm9CLFVBQTNCLEVBQXVDbEIsU0FBdkMsRUFBa0RELFNBQWxELEVBQTZEa0MsZUFBN0QsRUFBOEU7QUFDNUUsTUFBSWtCLFlBQVksR0FBRyxDQUFuQjtBQUFBLE1BQ0lDLFlBQVksR0FBR2xDLFVBQVUsQ0FBQ04sTUFEOUI7QUFBQSxNQUVJSyxNQUFNLEdBQUcsQ0FGYjtBQUFBLE1BR0lFLE1BQU0sR0FBRyxDQUhiOztBQUtBLFNBQU9nQyxZQUFZLEdBQUdDLFlBQXRCLEVBQW9DRCxZQUFZLEVBQWhELEVBQW9EO0FBQ2xELFFBQUlFLFNBQVMsR0FBR25DLFVBQVUsQ0FBQ2lDLFlBQUQsQ0FBMUI7O0FBQ0EsUUFBSSxDQUFDRSxTQUFTLENBQUNoQixPQUFmLEVBQXdCO0FBQ3RCLFVBQUksQ0FBQ2dCLFNBQVMsQ0FBQ2pCLEtBQVgsSUFBb0JILGVBQXhCLEVBQXlDO0FBQ3ZDLFlBQUk1QixLQUFLLEdBQUdMLFNBQVMsQ0FBQ3NELEtBQVYsQ0FBZ0JyQyxNQUFoQixFQUF3QkEsTUFBTSxHQUFHb0MsU0FBUyxDQUFDL0IsS0FBM0MsQ0FBWjtBQUNBakIsUUFBQUEsS0FBSyxHQUFHQSxLQUFLLENBQUNrRCxHQUFOLENBQVUsVUFBU2xELEtBQVQsRUFBZ0IyQyxDQUFoQixFQUFtQjtBQUNuQyxjQUFJUSxRQUFRLEdBQUd6RCxTQUFTLENBQUNvQixNQUFNLEdBQUc2QixDQUFWLENBQXhCO0FBQ0EsaUJBQU9RLFFBQVEsQ0FBQzVDLE1BQVQsR0FBa0JQLEtBQUssQ0FBQ08sTUFBeEIsR0FBaUM0QyxRQUFqQyxHQUE0Q25ELEtBQW5EO0FBQ0QsU0FITyxDQUFSO0FBS0FnRCxRQUFBQSxTQUFTLENBQUNoRCxLQUFWLEdBQWtCUCxJQUFJLENBQUN1QixJQUFMLENBQVVoQixLQUFWLENBQWxCO0FBQ0QsT0FSRCxNQVFPO0FBQ0xnRCxRQUFBQSxTQUFTLENBQUNoRCxLQUFWLEdBQWtCUCxJQUFJLENBQUN1QixJQUFMLENBQVVyQixTQUFTLENBQUNzRCxLQUFWLENBQWdCckMsTUFBaEIsRUFBd0JBLE1BQU0sR0FBR29DLFNBQVMsQ0FBQy9CLEtBQTNDLENBQVYsQ0FBbEI7QUFDRDs7QUFDREwsTUFBQUEsTUFBTSxJQUFJb0MsU0FBUyxDQUFDL0IsS0FBcEIsQ0Fac0IsQ0FjdEI7O0FBQ0EsVUFBSSxDQUFDK0IsU0FBUyxDQUFDakIsS0FBZixFQUFzQjtBQUNwQmpCLFFBQUFBLE1BQU0sSUFBSWtDLFNBQVMsQ0FBQy9CLEtBQXBCO0FBQ0Q7QUFDRixLQWxCRCxNQWtCTztBQUNMK0IsTUFBQUEsU0FBUyxDQUFDaEQsS0FBVixHQUFrQlAsSUFBSSxDQUFDdUIsSUFBTCxDQUFVdEIsU0FBUyxDQUFDdUQsS0FBVixDQUFnQm5DLE1BQWhCLEVBQXdCQSxNQUFNLEdBQUdrQyxTQUFTLENBQUMvQixLQUEzQyxDQUFWLENBQWxCO0FBQ0FILE1BQUFBLE1BQU0sSUFBSWtDLFNBQVMsQ0FBQy9CLEtBQXBCLENBRkssQ0FJTDtBQUNBO0FBQ0E7O0FBQ0EsVUFBSTZCLFlBQVksSUFBSWpDLFVBQVUsQ0FBQ2lDLFlBQVksR0FBRyxDQUFoQixDQUFWLENBQTZCZixLQUFqRCxFQUF3RDtBQUN0RCxZQUFJcUIsR0FBRyxHQUFHdkMsVUFBVSxDQUFDaUMsWUFBWSxHQUFHLENBQWhCLENBQXBCO0FBQ0FqQyxRQUFBQSxVQUFVLENBQUNpQyxZQUFZLEdBQUcsQ0FBaEIsQ0FBVixHQUErQmpDLFVBQVUsQ0FBQ2lDLFlBQUQsQ0FBekM7QUFDQWpDLFFBQUFBLFVBQVUsQ0FBQ2lDLFlBQUQsQ0FBVixHQUEyQk0sR0FBM0I7QUFDRDtBQUNGO0FBQ0YsR0F2QzJFLENBeUM1RTtBQUNBO0FBQ0E7OztBQUNBLE1BQUlDLGFBQWEsR0FBR3hDLFVBQVUsQ0FBQ2tDLFlBQVksR0FBRyxDQUFoQixDQUE5Qjs7QUFDQSxNQUFJQSxZQUFZLEdBQUcsQ0FBZixJQUNHLE9BQU9NLGFBQWEsQ0FBQ3JELEtBQXJCLEtBQStCLFFBRGxDLEtBRUlxRCxhQUFhLENBQUN0QixLQUFkLElBQXVCc0IsYUFBYSxDQUFDckIsT0FGekMsS0FHR3ZDLElBQUksQ0FBQzJDLE1BQUwsQ0FBWSxFQUFaLEVBQWdCaUIsYUFBYSxDQUFDckQsS0FBOUIsQ0FIUCxFQUc2QztBQUMzQ2EsSUFBQUEsVUFBVSxDQUFDa0MsWUFBWSxHQUFHLENBQWhCLENBQVYsQ0FBNkIvQyxLQUE3QixJQUFzQ3FELGFBQWEsQ0FBQ3JELEtBQXBEO0FBQ0FhLElBQUFBLFVBQVUsQ0FBQ3lDLEdBQVg7QUFDRDs7QUFFRCxTQUFPekMsVUFBUDtBQUNEOztBQUVELFNBQVNZLFNBQVQsQ0FBbUI4QixJQUFuQixFQUF5QjtBQUN2QixTQUFPO0FBQUUzQyxJQUFBQSxNQUFNLEVBQUUyQyxJQUFJLENBQUMzQyxNQUFmO0FBQXVCQyxJQUFBQSxVQUFVLEVBQUUwQyxJQUFJLENBQUMxQyxVQUFMLENBQWdCb0MsS0FBaEIsQ0FBc0IsQ0FBdEI7QUFBbkMsR0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gRGlmZigpIHt9XG5cbkRpZmYucHJvdG90eXBlID0ge1xuICBkaWZmKG9sZFN0cmluZywgbmV3U3RyaW5nLCBvcHRpb25zID0ge30pIHtcbiAgICBsZXQgY2FsbGJhY2sgPSBvcHRpb25zLmNhbGxiYWNrO1xuICAgIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY2FsbGJhY2sgPSBvcHRpb25zO1xuICAgICAgb3B0aW9ucyA9IHt9O1xuICAgIH1cbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuXG4gICAgbGV0IHNlbGYgPSB0aGlzO1xuXG4gICAgZnVuY3Rpb24gZG9uZSh2YWx1ZSkge1xuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7IGNhbGxiYWNrKHVuZGVmaW5lZCwgdmFsdWUpOyB9LCAwKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQWxsb3cgc3ViY2xhc3NlcyB0byBtYXNzYWdlIHRoZSBpbnB1dCBwcmlvciB0byBydW5uaW5nXG4gICAgb2xkU3RyaW5nID0gdGhpcy5jYXN0SW5wdXQob2xkU3RyaW5nKTtcbiAgICBuZXdTdHJpbmcgPSB0aGlzLmNhc3RJbnB1dChuZXdTdHJpbmcpO1xuXG4gICAgb2xkU3RyaW5nID0gdGhpcy5yZW1vdmVFbXB0eSh0aGlzLnRva2VuaXplKG9sZFN0cmluZykpO1xuICAgIG5ld1N0cmluZyA9IHRoaXMucmVtb3ZlRW1wdHkodGhpcy50b2tlbml6ZShuZXdTdHJpbmcpKTtcblxuICAgIGxldCBuZXdMZW4gPSBuZXdTdHJpbmcubGVuZ3RoLCBvbGRMZW4gPSBvbGRTdHJpbmcubGVuZ3RoO1xuICAgIGxldCBlZGl0TGVuZ3RoID0gMTtcbiAgICBsZXQgbWF4RWRpdExlbmd0aCA9IG5ld0xlbiArIG9sZExlbjtcbiAgICBsZXQgYmVzdFBhdGggPSBbeyBuZXdQb3M6IC0xLCBjb21wb25lbnRzOiBbXSB9XTtcblxuICAgIC8vIFNlZWQgZWRpdExlbmd0aCA9IDAsIGkuZS4gdGhlIGNvbnRlbnQgc3RhcnRzIHdpdGggdGhlIHNhbWUgdmFsdWVzXG4gICAgbGV0IG9sZFBvcyA9IHRoaXMuZXh0cmFjdENvbW1vbihiZXN0UGF0aFswXSwgbmV3U3RyaW5nLCBvbGRTdHJpbmcsIDApO1xuICAgIGlmIChiZXN0UGF0aFswXS5uZXdQb3MgKyAxID49IG5ld0xlbiAmJiBvbGRQb3MgKyAxID49IG9sZExlbikge1xuICAgICAgLy8gSWRlbnRpdHkgcGVyIHRoZSBlcXVhbGl0eSBhbmQgdG9rZW5pemVyXG4gICAgICByZXR1cm4gZG9uZShbe3ZhbHVlOiB0aGlzLmpvaW4obmV3U3RyaW5nKSwgY291bnQ6IG5ld1N0cmluZy5sZW5ndGh9XSk7XG4gICAgfVxuXG4gICAgLy8gTWFpbiB3b3JrZXIgbWV0aG9kLiBjaGVja3MgYWxsIHBlcm11dGF0aW9ucyBvZiBhIGdpdmVuIGVkaXQgbGVuZ3RoIGZvciBhY2NlcHRhbmNlLlxuICAgIGZ1bmN0aW9uIGV4ZWNFZGl0TGVuZ3RoKCkge1xuICAgICAgZm9yIChsZXQgZGlhZ29uYWxQYXRoID0gLTEgKiBlZGl0TGVuZ3RoOyBkaWFnb25hbFBhdGggPD0gZWRpdExlbmd0aDsgZGlhZ29uYWxQYXRoICs9IDIpIHtcbiAgICAgICAgbGV0IGJhc2VQYXRoO1xuICAgICAgICBsZXQgYWRkUGF0aCA9IGJlc3RQYXRoW2RpYWdvbmFsUGF0aCAtIDFdLFxuICAgICAgICAgICAgcmVtb3ZlUGF0aCA9IGJlc3RQYXRoW2RpYWdvbmFsUGF0aCArIDFdLFxuICAgICAgICAgICAgb2xkUG9zID0gKHJlbW92ZVBhdGggPyByZW1vdmVQYXRoLm5ld1BvcyA6IDApIC0gZGlhZ29uYWxQYXRoO1xuICAgICAgICBpZiAoYWRkUGF0aCkge1xuICAgICAgICAgIC8vIE5vIG9uZSBlbHNlIGlzIGdvaW5nIHRvIGF0dGVtcHQgdG8gdXNlIHRoaXMgdmFsdWUsIGNsZWFyIGl0XG4gICAgICAgICAgYmVzdFBhdGhbZGlhZ29uYWxQYXRoIC0gMV0gPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgY2FuQWRkID0gYWRkUGF0aCAmJiBhZGRQYXRoLm5ld1BvcyArIDEgPCBuZXdMZW4sXG4gICAgICAgICAgICBjYW5SZW1vdmUgPSByZW1vdmVQYXRoICYmIDAgPD0gb2xkUG9zICYmIG9sZFBvcyA8IG9sZExlbjtcbiAgICAgICAgaWYgKCFjYW5BZGQgJiYgIWNhblJlbW92ZSkge1xuICAgICAgICAgIC8vIElmIHRoaXMgcGF0aCBpcyBhIHRlcm1pbmFsIHRoZW4gcHJ1bmVcbiAgICAgICAgICBiZXN0UGF0aFtkaWFnb25hbFBhdGhdID0gdW5kZWZpbmVkO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2VsZWN0IHRoZSBkaWFnb25hbCB0aGF0IHdlIHdhbnQgdG8gYnJhbmNoIGZyb20uIFdlIHNlbGVjdCB0aGUgcHJpb3JcbiAgICAgICAgLy8gcGF0aCB3aG9zZSBwb3NpdGlvbiBpbiB0aGUgbmV3IHN0cmluZyBpcyB0aGUgZmFydGhlc3QgZnJvbSB0aGUgb3JpZ2luXG4gICAgICAgIC8vIGFuZCBkb2VzIG5vdCBwYXNzIHRoZSBib3VuZHMgb2YgdGhlIGRpZmYgZ3JhcGhcbiAgICAgICAgaWYgKCFjYW5BZGQgfHwgKGNhblJlbW92ZSAmJiBhZGRQYXRoLm5ld1BvcyA8IHJlbW92ZVBhdGgubmV3UG9zKSkge1xuICAgICAgICAgIGJhc2VQYXRoID0gY2xvbmVQYXRoKHJlbW92ZVBhdGgpO1xuICAgICAgICAgIHNlbGYucHVzaENvbXBvbmVudChiYXNlUGF0aC5jb21wb25lbnRzLCB1bmRlZmluZWQsIHRydWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGJhc2VQYXRoID0gYWRkUGF0aDsgLy8gTm8gbmVlZCB0byBjbG9uZSwgd2UndmUgcHVsbGVkIGl0IGZyb20gdGhlIGxpc3RcbiAgICAgICAgICBiYXNlUGF0aC5uZXdQb3MrKztcbiAgICAgICAgICBzZWxmLnB1c2hDb21wb25lbnQoYmFzZVBhdGguY29tcG9uZW50cywgdHJ1ZSwgdW5kZWZpbmVkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG9sZFBvcyA9IHNlbGYuZXh0cmFjdENvbW1vbihiYXNlUGF0aCwgbmV3U3RyaW5nLCBvbGRTdHJpbmcsIGRpYWdvbmFsUGF0aCk7XG5cbiAgICAgICAgLy8gSWYgd2UgaGF2ZSBoaXQgdGhlIGVuZCBvZiBib3RoIHN0cmluZ3MsIHRoZW4gd2UgYXJlIGRvbmVcbiAgICAgICAgaWYgKGJhc2VQYXRoLm5ld1BvcyArIDEgPj0gbmV3TGVuICYmIG9sZFBvcyArIDEgPj0gb2xkTGVuKSB7XG4gICAgICAgICAgcmV0dXJuIGRvbmUoYnVpbGRWYWx1ZXMoc2VsZiwgYmFzZVBhdGguY29tcG9uZW50cywgbmV3U3RyaW5nLCBvbGRTdHJpbmcsIHNlbGYudXNlTG9uZ2VzdFRva2VuKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gT3RoZXJ3aXNlIHRyYWNrIHRoaXMgcGF0aCBhcyBhIHBvdGVudGlhbCBjYW5kaWRhdGUgYW5kIGNvbnRpbnVlLlxuICAgICAgICAgIGJlc3RQYXRoW2RpYWdvbmFsUGF0aF0gPSBiYXNlUGF0aDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBlZGl0TGVuZ3RoKys7XG4gICAgfVxuXG4gICAgLy8gUGVyZm9ybXMgdGhlIGxlbmd0aCBvZiBlZGl0IGl0ZXJhdGlvbi4gSXMgYSBiaXQgZnVnbHkgYXMgdGhpcyBoYXMgdG8gc3VwcG9ydCB0aGVcbiAgICAvLyBzeW5jIGFuZCBhc3luYyBtb2RlIHdoaWNoIGlzIG5ldmVyIGZ1bi4gTG9vcHMgb3ZlciBleGVjRWRpdExlbmd0aCB1bnRpbCBhIHZhbHVlXG4gICAgLy8gaXMgcHJvZHVjZWQuXG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAoZnVuY3Rpb24gZXhlYygpIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAvLyBUaGlzIHNob3VsZCBub3QgaGFwcGVuLCBidXQgd2Ugd2FudCB0byBiZSBzYWZlLlxuICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgICAgaWYgKGVkaXRMZW5ndGggPiBtYXhFZGl0TGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIWV4ZWNFZGl0TGVuZ3RoKCkpIHtcbiAgICAgICAgICAgIGV4ZWMoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sIDApO1xuICAgICAgfSgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2hpbGUgKGVkaXRMZW5ndGggPD0gbWF4RWRpdExlbmd0aCkge1xuICAgICAgICBsZXQgcmV0ID0gZXhlY0VkaXRMZW5ndGgoKTtcbiAgICAgICAgaWYgKHJldCkge1xuICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0sXG5cbiAgcHVzaENvbXBvbmVudChjb21wb25lbnRzLCBhZGRlZCwgcmVtb3ZlZCkge1xuICAgIGxldCBsYXN0ID0gY29tcG9uZW50c1tjb21wb25lbnRzLmxlbmd0aCAtIDFdO1xuICAgIGlmIChsYXN0ICYmIGxhc3QuYWRkZWQgPT09IGFkZGVkICYmIGxhc3QucmVtb3ZlZCA9PT0gcmVtb3ZlZCkge1xuICAgICAgLy8gV2UgbmVlZCB0byBjbG9uZSBoZXJlIGFzIHRoZSBjb21wb25lbnQgY2xvbmUgb3BlcmF0aW9uIGlzIGp1c3RcbiAgICAgIC8vIGFzIHNoYWxsb3cgYXJyYXkgY2xvbmVcbiAgICAgIGNvbXBvbmVudHNbY29tcG9uZW50cy5sZW5ndGggLSAxXSA9IHtjb3VudDogbGFzdC5jb3VudCArIDEsIGFkZGVkOiBhZGRlZCwgcmVtb3ZlZDogcmVtb3ZlZCB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb21wb25lbnRzLnB1c2goe2NvdW50OiAxLCBhZGRlZDogYWRkZWQsIHJlbW92ZWQ6IHJlbW92ZWQgfSk7XG4gICAgfVxuICB9LFxuICBleHRyYWN0Q29tbW9uKGJhc2VQYXRoLCBuZXdTdHJpbmcsIG9sZFN0cmluZywgZGlhZ29uYWxQYXRoKSB7XG4gICAgbGV0IG5ld0xlbiA9IG5ld1N0cmluZy5sZW5ndGgsXG4gICAgICAgIG9sZExlbiA9IG9sZFN0cmluZy5sZW5ndGgsXG4gICAgICAgIG5ld1BvcyA9IGJhc2VQYXRoLm5ld1BvcyxcbiAgICAgICAgb2xkUG9zID0gbmV3UG9zIC0gZGlhZ29uYWxQYXRoLFxuXG4gICAgICAgIGNvbW1vbkNvdW50ID0gMDtcbiAgICB3aGlsZSAobmV3UG9zICsgMSA8IG5ld0xlbiAmJiBvbGRQb3MgKyAxIDwgb2xkTGVuICYmIHRoaXMuZXF1YWxzKG5ld1N0cmluZ1tuZXdQb3MgKyAxXSwgb2xkU3RyaW5nW29sZFBvcyArIDFdKSkge1xuICAgICAgbmV3UG9zKys7XG4gICAgICBvbGRQb3MrKztcbiAgICAgIGNvbW1vbkNvdW50Kys7XG4gICAgfVxuXG4gICAgaWYgKGNvbW1vbkNvdW50KSB7XG4gICAgICBiYXNlUGF0aC5jb21wb25lbnRzLnB1c2goe2NvdW50OiBjb21tb25Db3VudH0pO1xuICAgIH1cblxuICAgIGJhc2VQYXRoLm5ld1BvcyA9IG5ld1BvcztcbiAgICByZXR1cm4gb2xkUG9zO1xuICB9LFxuXG4gIGVxdWFscyhsZWZ0LCByaWdodCkge1xuICAgIGlmICh0aGlzLm9wdGlvbnMuY29tcGFyYXRvcikge1xuICAgICAgcmV0dXJuIHRoaXMub3B0aW9ucy5jb21wYXJhdG9yKGxlZnQsIHJpZ2h0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGxlZnQgPT09IHJpZ2h0XG4gICAgICAgIHx8ICh0aGlzLm9wdGlvbnMuaWdub3JlQ2FzZSAmJiBsZWZ0LnRvTG93ZXJDYXNlKCkgPT09IHJpZ2h0LnRvTG93ZXJDYXNlKCkpO1xuICAgIH1cbiAgfSxcbiAgcmVtb3ZlRW1wdHkoYXJyYXkpIHtcbiAgICBsZXQgcmV0ID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGFycmF5W2ldKSB7XG4gICAgICAgIHJldC5wdXNoKGFycmF5W2ldKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbiAgfSxcbiAgY2FzdElucHV0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9LFxuICB0b2tlbml6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5zcGxpdCgnJyk7XG4gIH0sXG4gIGpvaW4oY2hhcnMpIHtcbiAgICByZXR1cm4gY2hhcnMuam9pbignJyk7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGJ1aWxkVmFsdWVzKGRpZmYsIGNvbXBvbmVudHMsIG5ld1N0cmluZywgb2xkU3RyaW5nLCB1c2VMb25nZXN0VG9rZW4pIHtcbiAgbGV0IGNvbXBvbmVudFBvcyA9IDAsXG4gICAgICBjb21wb25lbnRMZW4gPSBjb21wb25lbnRzLmxlbmd0aCxcbiAgICAgIG5ld1BvcyA9IDAsXG4gICAgICBvbGRQb3MgPSAwO1xuXG4gIGZvciAoOyBjb21wb25lbnRQb3MgPCBjb21wb25lbnRMZW47IGNvbXBvbmVudFBvcysrKSB7XG4gICAgbGV0IGNvbXBvbmVudCA9IGNvbXBvbmVudHNbY29tcG9uZW50UG9zXTtcbiAgICBpZiAoIWNvbXBvbmVudC5yZW1vdmVkKSB7XG4gICAgICBpZiAoIWNvbXBvbmVudC5hZGRlZCAmJiB1c2VMb25nZXN0VG9rZW4pIHtcbiAgICAgICAgbGV0IHZhbHVlID0gbmV3U3RyaW5nLnNsaWNlKG5ld1BvcywgbmV3UG9zICsgY29tcG9uZW50LmNvdW50KTtcbiAgICAgICAgdmFsdWUgPSB2YWx1ZS5tYXAoZnVuY3Rpb24odmFsdWUsIGkpIHtcbiAgICAgICAgICBsZXQgb2xkVmFsdWUgPSBvbGRTdHJpbmdbb2xkUG9zICsgaV07XG4gICAgICAgICAgcmV0dXJuIG9sZFZhbHVlLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCA/IG9sZFZhbHVlIDogdmFsdWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbXBvbmVudC52YWx1ZSA9IGRpZmYuam9pbih2YWx1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb21wb25lbnQudmFsdWUgPSBkaWZmLmpvaW4obmV3U3RyaW5nLnNsaWNlKG5ld1BvcywgbmV3UG9zICsgY29tcG9uZW50LmNvdW50KSk7XG4gICAgICB9XG4gICAgICBuZXdQb3MgKz0gY29tcG9uZW50LmNvdW50O1xuXG4gICAgICAvLyBDb21tb24gY2FzZVxuICAgICAgaWYgKCFjb21wb25lbnQuYWRkZWQpIHtcbiAgICAgICAgb2xkUG9zICs9IGNvbXBvbmVudC5jb3VudDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29tcG9uZW50LnZhbHVlID0gZGlmZi5qb2luKG9sZFN0cmluZy5zbGljZShvbGRQb3MsIG9sZFBvcyArIGNvbXBvbmVudC5jb3VudCkpO1xuICAgICAgb2xkUG9zICs9IGNvbXBvbmVudC5jb3VudDtcblxuICAgICAgLy8gUmV2ZXJzZSBhZGQgYW5kIHJlbW92ZSBzbyByZW1vdmVzIGFyZSBvdXRwdXQgZmlyc3QgdG8gbWF0Y2ggY29tbW9uIGNvbnZlbnRpb25cbiAgICAgIC8vIFRoZSBkaWZmaW5nIGFsZ29yaXRobSBpcyB0aWVkIHRvIGFkZCB0aGVuIHJlbW92ZSBvdXRwdXQgYW5kIHRoaXMgaXMgdGhlIHNpbXBsZXN0XG4gICAgICAvLyByb3V0ZSB0byBnZXQgdGhlIGRlc2lyZWQgb3V0cHV0IHdpdGggbWluaW1hbCBvdmVyaGVhZC5cbiAgICAgIGlmIChjb21wb25lbnRQb3MgJiYgY29tcG9uZW50c1tjb21wb25lbnRQb3MgLSAxXS5hZGRlZCkge1xuICAgICAgICBsZXQgdG1wID0gY29tcG9uZW50c1tjb21wb25lbnRQb3MgLSAxXTtcbiAgICAgICAgY29tcG9uZW50c1tjb21wb25lbnRQb3MgLSAxXSA9IGNvbXBvbmVudHNbY29tcG9uZW50UG9zXTtcbiAgICAgICAgY29tcG9uZW50c1tjb21wb25lbnRQb3NdID0gdG1wO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIFNwZWNpYWwgY2FzZSBoYW5kbGUgZm9yIHdoZW4gb25lIHRlcm1pbmFsIGlzIGlnbm9yZWQgKGkuZS4gd2hpdGVzcGFjZSkuXG4gIC8vIEZvciB0aGlzIGNhc2Ugd2UgbWVyZ2UgdGhlIHRlcm1pbmFsIGludG8gdGhlIHByaW9yIHN0cmluZyBhbmQgZHJvcCB0aGUgY2hhbmdlLlxuICAvLyBUaGlzIGlzIG9ubHkgYXZhaWxhYmxlIGZvciBzdHJpbmcgbW9kZS5cbiAgbGV0IGxhc3RDb21wb25lbnQgPSBjb21wb25lbnRzW2NvbXBvbmVudExlbiAtIDFdO1xuICBpZiAoY29tcG9uZW50TGVuID4gMVxuICAgICAgJiYgdHlwZW9mIGxhc3RDb21wb25lbnQudmFsdWUgPT09ICdzdHJpbmcnXG4gICAgICAmJiAobGFzdENvbXBvbmVudC5hZGRlZCB8fCBsYXN0Q29tcG9uZW50LnJlbW92ZWQpXG4gICAgICAmJiBkaWZmLmVxdWFscygnJywgbGFzdENvbXBvbmVudC52YWx1ZSkpIHtcbiAgICBjb21wb25lbnRzW2NvbXBvbmVudExlbiAtIDJdLnZhbHVlICs9IGxhc3RDb21wb25lbnQudmFsdWU7XG4gICAgY29tcG9uZW50cy5wb3AoKTtcbiAgfVxuXG4gIHJldHVybiBjb21wb25lbnRzO1xufVxuXG5mdW5jdGlvbiBjbG9uZVBhdGgocGF0aCkge1xuICByZXR1cm4geyBuZXdQb3M6IHBhdGgubmV3UG9zLCBjb21wb25lbnRzOiBwYXRoLmNvbXBvbmVudHMuc2xpY2UoMCkgfTtcbn1cbiJdfQ==
diff --git a/node_modules/libtap/node_modules/diff/lib/diff/character.js b/node_modules/libtap/node_modules/diff/lib/diff/character.js
new file mode 100644
index 0000000000000..4722b16281956
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/diff/character.js
@@ -0,0 +1,37 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.diffChars = diffChars;
+exports.characterDiff = void 0;
+
+/*istanbul ignore end*/
+var
+/*istanbul ignore start*/
+_base = _interopRequireDefault(require("./base"))
+/*istanbul ignore end*/
+;
+
+/*istanbul ignore start*/ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/*istanbul ignore end*/
+var characterDiff = new
+/*istanbul ignore start*/
+_base
+/*istanbul ignore end*/
+.
+/*istanbul ignore start*/
+default
+/*istanbul ignore end*/
+();
+
+/*istanbul ignore start*/
+exports.characterDiff = characterDiff;
+
+/*istanbul ignore end*/
+function diffChars(oldStr, newStr, options) {
+  return characterDiff.diff(oldStr, newStr, options);
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2NoYXJhY3Rlci5qcyJdLCJuYW1lcyI6WyJjaGFyYWN0ZXJEaWZmIiwiRGlmZiIsImRpZmZDaGFycyIsIm9sZFN0ciIsIm5ld1N0ciIsIm9wdGlvbnMiLCJkaWZmIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7Ozs7QUFFTyxJQUFNQSxhQUFhLEdBQUc7QUFBSUM7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBSjtBQUFBLEVBQXRCOzs7Ozs7QUFDQSxTQUFTQyxTQUFULENBQW1CQyxNQUFuQixFQUEyQkMsTUFBM0IsRUFBbUNDLE9BQW5DLEVBQTRDO0FBQUUsU0FBT0wsYUFBYSxDQUFDTSxJQUFkLENBQW1CSCxNQUFuQixFQUEyQkMsTUFBM0IsRUFBbUNDLE9BQW5DLENBQVA7QUFBcUQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRGlmZiBmcm9tICcuL2Jhc2UnO1xuXG5leHBvcnQgY29uc3QgY2hhcmFjdGVyRGlmZiA9IG5ldyBEaWZmKCk7XG5leHBvcnQgZnVuY3Rpb24gZGlmZkNoYXJzKG9sZFN0ciwgbmV3U3RyLCBvcHRpb25zKSB7IHJldHVybiBjaGFyYWN0ZXJEaWZmLmRpZmYob2xkU3RyLCBuZXdTdHIsIG9wdGlvbnMpOyB9XG4iXX0=
diff --git a/node_modules/libtap/node_modules/diff/lib/diff/css.js b/node_modules/libtap/node_modules/diff/lib/diff/css.js
new file mode 100644
index 0000000000000..69ba47ec8f1b3
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/diff/css.js
@@ -0,0 +1,41 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.diffCss = diffCss;
+exports.cssDiff = void 0;
+
+/*istanbul ignore end*/
+var
+/*istanbul ignore start*/
+_base = _interopRequireDefault(require("./base"))
+/*istanbul ignore end*/
+;
+
+/*istanbul ignore start*/ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/*istanbul ignore end*/
+var cssDiff = new
+/*istanbul ignore start*/
+_base
+/*istanbul ignore end*/
+.
+/*istanbul ignore start*/
+default
+/*istanbul ignore end*/
+();
+
+/*istanbul ignore start*/
+exports.cssDiff = cssDiff;
+
+/*istanbul ignore end*/
+cssDiff.tokenize = function (value) {
+  return value.split(/([{}:;,]|\s+)/);
+};
+
+function diffCss(oldStr, newStr, callback) {
+  return cssDiff.diff(oldStr, newStr, callback);
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2Nzcy5qcyJdLCJuYW1lcyI6WyJjc3NEaWZmIiwiRGlmZiIsInRva2VuaXplIiwidmFsdWUiLCJzcGxpdCIsImRpZmZDc3MiLCJvbGRTdHIiLCJuZXdTdHIiLCJjYWxsYmFjayIsImRpZmYiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOzs7OztBQUVPLElBQU1BLE9BQU8sR0FBRztBQUFJQztBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFKO0FBQUEsRUFBaEI7Ozs7OztBQUNQRCxPQUFPLENBQUNFLFFBQVIsR0FBbUIsVUFBU0MsS0FBVCxFQUFnQjtBQUNqQyxTQUFPQSxLQUFLLENBQUNDLEtBQU4sQ0FBWSxlQUFaLENBQVA7QUFDRCxDQUZEOztBQUlPLFNBQVNDLE9BQVQsQ0FBaUJDLE1BQWpCLEVBQXlCQyxNQUF6QixFQUFpQ0MsUUFBakMsRUFBMkM7QUFBRSxTQUFPUixPQUFPLENBQUNTLElBQVIsQ0FBYUgsTUFBYixFQUFxQkMsTUFBckIsRUFBNkJDLFFBQTdCLENBQVA7QUFBZ0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRGlmZiBmcm9tICcuL2Jhc2UnO1xuXG5leHBvcnQgY29uc3QgY3NzRGlmZiA9IG5ldyBEaWZmKCk7XG5jc3NEaWZmLnRva2VuaXplID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlLnNwbGl0KC8oW3t9OjssXXxcXHMrKS8pO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGRpZmZDc3Mob2xkU3RyLCBuZXdTdHIsIGNhbGxiYWNrKSB7IHJldHVybiBjc3NEaWZmLmRpZmYob2xkU3RyLCBuZXdTdHIsIGNhbGxiYWNrKTsgfVxuIl19
diff --git a/node_modules/libtap/node_modules/diff/lib/diff/json.js b/node_modules/libtap/node_modules/diff/lib/diff/json.js
new file mode 100644
index 0000000000000..715ef0886b2c0
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/diff/json.js
@@ -0,0 +1,163 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.diffJson = diffJson;
+exports.canonicalize = canonicalize;
+exports.jsonDiff = void 0;
+
+/*istanbul ignore end*/
+var
+/*istanbul ignore start*/
+_base = _interopRequireDefault(require("./base"))
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_line = require("./line")
+/*istanbul ignore end*/
+;
+
+/*istanbul ignore start*/ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+/*istanbul ignore end*/
+var objectPrototypeToString = Object.prototype.toString;
+var jsonDiff = new
+/*istanbul ignore start*/
+_base
+/*istanbul ignore end*/
+.
+/*istanbul ignore start*/
+default
+/*istanbul ignore end*/
+(); // Discriminate between two lines of pretty-printed, serialized JSON where one of them has a
+// dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output:
+
+/*istanbul ignore start*/
+exports.jsonDiff = jsonDiff;
+
+/*istanbul ignore end*/
+jsonDiff.useLongestToken = true;
+jsonDiff.tokenize =
+/*istanbul ignore start*/
+_line
+/*istanbul ignore end*/
+.
+/*istanbul ignore start*/
+lineDiff
+/*istanbul ignore end*/
+.tokenize;
+
+jsonDiff.castInput = function (value) {
+  /*istanbul ignore start*/
+  var _this$options =
+  /*istanbul ignore end*/
+  this.options,
+      undefinedReplacement = _this$options.undefinedReplacement,
+      _this$options$stringi = _this$options.stringifyReplacer,
+      stringifyReplacer = _this$options$stringi === void 0 ? function (k, v)
+  /*istanbul ignore start*/
+  {
+    return (
+      /*istanbul ignore end*/
+      typeof v === 'undefined' ? undefinedReplacement : v
+    );
+  } : _this$options$stringi;
+  return typeof value === 'string' ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), stringifyReplacer, '  ');
+};
+
+jsonDiff.equals = function (left, right) {
+  return (
+    /*istanbul ignore start*/
+    _base
+    /*istanbul ignore end*/
+    .
+    /*istanbul ignore start*/
+    default
+    /*istanbul ignore end*/
+    .prototype.equals.call(jsonDiff, left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1'))
+  );
+};
+
+function diffJson(oldObj, newObj, options) {
+  return jsonDiff.diff(oldObj, newObj, options);
+} // This function handles the presence of circular references by bailing out when encountering an
+// object that is already on the "stack" of items being processed. Accepts an optional replacer
+
+
+function canonicalize(obj, stack, replacementStack, replacer, key) {
+  stack = stack || [];
+  replacementStack = replacementStack || [];
+
+  if (replacer) {
+    obj = replacer(key, obj);
+  }
+
+  var i;
+
+  for (i = 0; i < stack.length; i += 1) {
+    if (stack[i] === obj) {
+      return replacementStack[i];
+    }
+  }
+
+  var canonicalizedObj;
+
+  if ('[object Array]' === objectPrototypeToString.call(obj)) {
+    stack.push(obj);
+    canonicalizedObj = new Array(obj.length);
+    replacementStack.push(canonicalizedObj);
+
+    for (i = 0; i < obj.length; i += 1) {
+      canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack, replacer, key);
+    }
+
+    stack.pop();
+    replacementStack.pop();
+    return canonicalizedObj;
+  }
+
+  if (obj && obj.toJSON) {
+    obj = obj.toJSON();
+  }
+
+  if (
+  /*istanbul ignore start*/
+  _typeof(
+  /*istanbul ignore end*/
+  obj) === 'object' && obj !== null) {
+    stack.push(obj);
+    canonicalizedObj = {};
+    replacementStack.push(canonicalizedObj);
+
+    var sortedKeys = [],
+        _key;
+
+    for (_key in obj) {
+      /* istanbul ignore else */
+      if (obj.hasOwnProperty(_key)) {
+        sortedKeys.push(_key);
+      }
+    }
+
+    sortedKeys.sort();
+
+    for (i = 0; i < sortedKeys.length; i += 1) {
+      _key = sortedKeys[i];
+      canonicalizedObj[_key] = canonicalize(obj[_key], stack, replacementStack, replacer, _key);
+    }
+
+    stack.pop();
+    replacementStack.pop();
+  } else {
+    canonicalizedObj = obj;
+  }
+
+  return canonicalizedObj;
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2pzb24uanMiXSwibmFtZXMiOlsib2JqZWN0UHJvdG90eXBlVG9TdHJpbmciLCJPYmplY3QiLCJwcm90b3R5cGUiLCJ0b1N0cmluZyIsImpzb25EaWZmIiwiRGlmZiIsInVzZUxvbmdlc3RUb2tlbiIsInRva2VuaXplIiwibGluZURpZmYiLCJjYXN0SW5wdXQiLCJ2YWx1ZSIsIm9wdGlvbnMiLCJ1bmRlZmluZWRSZXBsYWNlbWVudCIsInN0cmluZ2lmeVJlcGxhY2VyIiwiayIsInYiLCJKU09OIiwic3RyaW5naWZ5IiwiY2Fub25pY2FsaXplIiwiZXF1YWxzIiwibGVmdCIsInJpZ2h0IiwiY2FsbCIsInJlcGxhY2UiLCJkaWZmSnNvbiIsIm9sZE9iaiIsIm5ld09iaiIsImRpZmYiLCJvYmoiLCJzdGFjayIsInJlcGxhY2VtZW50U3RhY2siLCJyZXBsYWNlciIsImtleSIsImkiLCJsZW5ndGgiLCJjYW5vbmljYWxpemVkT2JqIiwicHVzaCIsIkFycmF5IiwicG9wIiwidG9KU09OIiwic29ydGVkS2V5cyIsImhhc093blByb3BlcnR5Iiwic29ydCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOztBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7Ozs7Ozs7QUFFQSxJQUFNQSx1QkFBdUIsR0FBR0MsTUFBTSxDQUFDQyxTQUFQLENBQWlCQyxRQUFqRDtBQUdPLElBQU1DLFFBQVEsR0FBRztBQUFJQztBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFKO0FBQUEsRUFBakIsQyxDQUNQO0FBQ0E7Ozs7OztBQUNBRCxRQUFRLENBQUNFLGVBQVQsR0FBMkIsSUFBM0I7QUFFQUYsUUFBUSxDQUFDRyxRQUFUO0FBQW9CQztBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBO0FBQUEsQ0FBU0QsUUFBN0I7O0FBQ0FILFFBQVEsQ0FBQ0ssU0FBVCxHQUFxQixVQUFTQyxLQUFULEVBQWdCO0FBQUE7QUFBQTtBQUFBO0FBQytFLE9BQUtDLE9BRHBGO0FBQUEsTUFDNUJDLG9CQUQ0QixpQkFDNUJBLG9CQUQ0QjtBQUFBLDRDQUNOQyxpQkFETTtBQUFBLE1BQ05BLGlCQURNLHNDQUNjLFVBQUNDLENBQUQsRUFBSUMsQ0FBSjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQVUsYUFBT0EsQ0FBUCxLQUFhLFdBQWIsR0FBMkJILG9CQUEzQixHQUFrREc7QUFBNUQ7QUFBQSxHQURkO0FBR25DLFNBQU8sT0FBT0wsS0FBUCxLQUFpQixRQUFqQixHQUE0QkEsS0FBNUIsR0FBb0NNLElBQUksQ0FBQ0MsU0FBTCxDQUFlQyxZQUFZLENBQUNSLEtBQUQsRUFBUSxJQUFSLEVBQWMsSUFBZCxFQUFvQkcsaUJBQXBCLENBQTNCLEVBQW1FQSxpQkFBbkUsRUFBc0YsSUFBdEYsQ0FBM0M7QUFDRCxDQUpEOztBQUtBVCxRQUFRLENBQUNlLE1BQVQsR0FBa0IsVUFBU0MsSUFBVCxFQUFlQyxLQUFmLEVBQXNCO0FBQ3RDLFNBQU9oQjtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBO0FBQUEsS0FBS0gsU0FBTCxDQUFlaUIsTUFBZixDQUFzQkcsSUFBdEIsQ0FBMkJsQixRQUEzQixFQUFxQ2dCLElBQUksQ0FBQ0csT0FBTCxDQUFhLFlBQWIsRUFBMkIsSUFBM0IsQ0FBckMsRUFBdUVGLEtBQUssQ0FBQ0UsT0FBTixDQUFjLFlBQWQsRUFBNEIsSUFBNUIsQ0FBdkU7QUFBUDtBQUNELENBRkQ7O0FBSU8sU0FBU0MsUUFBVCxDQUFrQkMsTUFBbEIsRUFBMEJDLE1BQTFCLEVBQWtDZixPQUFsQyxFQUEyQztBQUFFLFNBQU9QLFFBQVEsQ0FBQ3VCLElBQVQsQ0FBY0YsTUFBZCxFQUFzQkMsTUFBdEIsRUFBOEJmLE9BQTlCLENBQVA7QUFBZ0QsQyxDQUVwRztBQUNBOzs7QUFDTyxTQUFTTyxZQUFULENBQXNCVSxHQUF0QixFQUEyQkMsS0FBM0IsRUFBa0NDLGdCQUFsQyxFQUFvREMsUUFBcEQsRUFBOERDLEdBQTlELEVBQW1FO0FBQ3hFSCxFQUFBQSxLQUFLLEdBQUdBLEtBQUssSUFBSSxFQUFqQjtBQUNBQyxFQUFBQSxnQkFBZ0IsR0FBR0EsZ0JBQWdCLElBQUksRUFBdkM7O0FBRUEsTUFBSUMsUUFBSixFQUFjO0FBQ1pILElBQUFBLEdBQUcsR0FBR0csUUFBUSxDQUFDQyxHQUFELEVBQU1KLEdBQU4sQ0FBZDtBQUNEOztBQUVELE1BQUlLLENBQUo7O0FBRUEsT0FBS0EsQ0FBQyxHQUFHLENBQVQsRUFBWUEsQ0FBQyxHQUFHSixLQUFLLENBQUNLLE1BQXRCLEVBQThCRCxDQUFDLElBQUksQ0FBbkMsRUFBc0M7QUFDcEMsUUFBSUosS0FBSyxDQUFDSSxDQUFELENBQUwsS0FBYUwsR0FBakIsRUFBc0I7QUFDcEIsYUFBT0UsZ0JBQWdCLENBQUNHLENBQUQsQ0FBdkI7QUFDRDtBQUNGOztBQUVELE1BQUlFLGdCQUFKOztBQUVBLE1BQUkscUJBQXFCbkMsdUJBQXVCLENBQUNzQixJQUF4QixDQUE2Qk0sR0FBN0IsQ0FBekIsRUFBNEQ7QUFDMURDLElBQUFBLEtBQUssQ0FBQ08sSUFBTixDQUFXUixHQUFYO0FBQ0FPLElBQUFBLGdCQUFnQixHQUFHLElBQUlFLEtBQUosQ0FBVVQsR0FBRyxDQUFDTSxNQUFkLENBQW5CO0FBQ0FKLElBQUFBLGdCQUFnQixDQUFDTSxJQUFqQixDQUFzQkQsZ0JBQXRCOztBQUNBLFNBQUtGLENBQUMsR0FBRyxDQUFULEVBQVlBLENBQUMsR0FBR0wsR0FBRyxDQUFDTSxNQUFwQixFQUE0QkQsQ0FBQyxJQUFJLENBQWpDLEVBQW9DO0FBQ2xDRSxNQUFBQSxnQkFBZ0IsQ0FBQ0YsQ0FBRCxDQUFoQixHQUFzQmYsWUFBWSxDQUFDVSxHQUFHLENBQUNLLENBQUQsQ0FBSixFQUFTSixLQUFULEVBQWdCQyxnQkFBaEIsRUFBa0NDLFFBQWxDLEVBQTRDQyxHQUE1QyxDQUFsQztBQUNEOztBQUNESCxJQUFBQSxLQUFLLENBQUNTLEdBQU47QUFDQVIsSUFBQUEsZ0JBQWdCLENBQUNRLEdBQWpCO0FBQ0EsV0FBT0gsZ0JBQVA7QUFDRDs7QUFFRCxNQUFJUCxHQUFHLElBQUlBLEdBQUcsQ0FBQ1csTUFBZixFQUF1QjtBQUNyQlgsSUFBQUEsR0FBRyxHQUFHQSxHQUFHLENBQUNXLE1BQUosRUFBTjtBQUNEOztBQUVEO0FBQUk7QUFBQTtBQUFBO0FBQU9YLEVBQUFBLEdBQVAsTUFBZSxRQUFmLElBQTJCQSxHQUFHLEtBQUssSUFBdkMsRUFBNkM7QUFDM0NDLElBQUFBLEtBQUssQ0FBQ08sSUFBTixDQUFXUixHQUFYO0FBQ0FPLElBQUFBLGdCQUFnQixHQUFHLEVBQW5CO0FBQ0FMLElBQUFBLGdCQUFnQixDQUFDTSxJQUFqQixDQUFzQkQsZ0JBQXRCOztBQUNBLFFBQUlLLFVBQVUsR0FBRyxFQUFqQjtBQUFBLFFBQ0lSLElBREo7O0FBRUEsU0FBS0EsSUFBTCxJQUFZSixHQUFaLEVBQWlCO0FBQ2Y7QUFDQSxVQUFJQSxHQUFHLENBQUNhLGNBQUosQ0FBbUJULElBQW5CLENBQUosRUFBNkI7QUFDM0JRLFFBQUFBLFVBQVUsQ0FBQ0osSUFBWCxDQUFnQkosSUFBaEI7QUFDRDtBQUNGOztBQUNEUSxJQUFBQSxVQUFVLENBQUNFLElBQVg7O0FBQ0EsU0FBS1QsQ0FBQyxHQUFHLENBQVQsRUFBWUEsQ0FBQyxHQUFHTyxVQUFVLENBQUNOLE1BQTNCLEVBQW1DRCxDQUFDLElBQUksQ0FBeEMsRUFBMkM7QUFDekNELE1BQUFBLElBQUcsR0FBR1EsVUFBVSxDQUFDUCxDQUFELENBQWhCO0FBQ0FFLE1BQUFBLGdCQUFnQixDQUFDSCxJQUFELENBQWhCLEdBQXdCZCxZQUFZLENBQUNVLEdBQUcsQ0FBQ0ksSUFBRCxDQUFKLEVBQVdILEtBQVgsRUFBa0JDLGdCQUFsQixFQUFvQ0MsUUFBcEMsRUFBOENDLElBQTlDLENBQXBDO0FBQ0Q7O0FBQ0RILElBQUFBLEtBQUssQ0FBQ1MsR0FBTjtBQUNBUixJQUFBQSxnQkFBZ0IsQ0FBQ1EsR0FBakI7QUFDRCxHQW5CRCxNQW1CTztBQUNMSCxJQUFBQSxnQkFBZ0IsR0FBR1AsR0FBbkI7QUFDRDs7QUFDRCxTQUFPTyxnQkFBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IERpZmYgZnJvbSAnLi9iYXNlJztcbmltcG9ydCB7bGluZURpZmZ9IGZyb20gJy4vbGluZSc7XG5cbmNvbnN0IG9iamVjdFByb3RvdHlwZVRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuXG5leHBvcnQgY29uc3QganNvbkRpZmYgPSBuZXcgRGlmZigpO1xuLy8gRGlzY3JpbWluYXRlIGJldHdlZW4gdHdvIGxpbmVzIG9mIHByZXR0eS1wcmludGVkLCBzZXJpYWxpemVkIEpTT04gd2hlcmUgb25lIG9mIHRoZW0gaGFzIGFcbi8vIGRhbmdsaW5nIGNvbW1hIGFuZCB0aGUgb3RoZXIgZG9lc24ndC4gVHVybnMgb3V0IGluY2x1ZGluZyB0aGUgZGFuZ2xpbmcgY29tbWEgeWllbGRzIHRoZSBuaWNlc3Qgb3V0cHV0OlxuanNvbkRpZmYudXNlTG9uZ2VzdFRva2VuID0gdHJ1ZTtcblxuanNvbkRpZmYudG9rZW5pemUgPSBsaW5lRGlmZi50b2tlbml6ZTtcbmpzb25EaWZmLmNhc3RJbnB1dCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIGNvbnN0IHt1bmRlZmluZWRSZXBsYWNlbWVudCwgc3RyaW5naWZ5UmVwbGFjZXIgPSAoaywgdikgPT4gdHlwZW9mIHYgPT09ICd1bmRlZmluZWQnID8gdW5kZWZpbmVkUmVwbGFjZW1lbnQgOiB2fSA9IHRoaXMub3B0aW9ucztcblxuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyA/IHZhbHVlIDogSlNPTi5zdHJpbmdpZnkoY2Fub25pY2FsaXplKHZhbHVlLCBudWxsLCBudWxsLCBzdHJpbmdpZnlSZXBsYWNlciksIHN0cmluZ2lmeVJlcGxhY2VyLCAnICAnKTtcbn07XG5qc29uRGlmZi5lcXVhbHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gRGlmZi5wcm90b3R5cGUuZXF1YWxzLmNhbGwoanNvbkRpZmYsIGxlZnQucmVwbGFjZSgvLChbXFxyXFxuXSkvZywgJyQxJyksIHJpZ2h0LnJlcGxhY2UoLywoW1xcclxcbl0pL2csICckMScpKTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBkaWZmSnNvbihvbGRPYmosIG5ld09iaiwgb3B0aW9ucykgeyByZXR1cm4ganNvbkRpZmYuZGlmZihvbGRPYmosIG5ld09iaiwgb3B0aW9ucyk7IH1cblxuLy8gVGhpcyBmdW5jdGlvbiBoYW5kbGVzIHRoZSBwcmVzZW5jZSBvZiBjaXJjdWxhciByZWZlcmVuY2VzIGJ5IGJhaWxpbmcgb3V0IHdoZW4gZW5jb3VudGVyaW5nIGFuXG4vLyBvYmplY3QgdGhhdCBpcyBhbHJlYWR5IG9uIHRoZSBcInN0YWNrXCIgb2YgaXRlbXMgYmVpbmcgcHJvY2Vzc2VkLiBBY2NlcHRzIGFuIG9wdGlvbmFsIHJlcGxhY2VyXG5leHBvcnQgZnVuY3Rpb24gY2Fub25pY2FsaXplKG9iaiwgc3RhY2ssIHJlcGxhY2VtZW50U3RhY2ssIHJlcGxhY2VyLCBrZXkpIHtcbiAgc3RhY2sgPSBzdGFjayB8fCBbXTtcbiAgcmVwbGFjZW1lbnRTdGFjayA9IHJlcGxhY2VtZW50U3RhY2sgfHwgW107XG5cbiAgaWYgKHJlcGxhY2VyKSB7XG4gICAgb2JqID0gcmVwbGFjZXIoa2V5LCBvYmopO1xuICB9XG5cbiAgbGV0IGk7XG5cbiAgZm9yIChpID0gMDsgaSA8IHN0YWNrLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgaWYgKHN0YWNrW2ldID09PSBvYmopIHtcbiAgICAgIHJldHVybiByZXBsYWNlbWVudFN0YWNrW2ldO1xuICAgIH1cbiAgfVxuXG4gIGxldCBjYW5vbmljYWxpemVkT2JqO1xuXG4gIGlmICgnW29iamVjdCBBcnJheV0nID09PSBvYmplY3RQcm90b3R5cGVUb1N0cmluZy5jYWxsKG9iaikpIHtcbiAgICBzdGFjay5wdXNoKG9iaik7XG4gICAgY2Fub25pY2FsaXplZE9iaiA9IG5ldyBBcnJheShvYmoubGVuZ3RoKTtcbiAgICByZXBsYWNlbWVudFN0YWNrLnB1c2goY2Fub25pY2FsaXplZE9iaik7XG4gICAgZm9yIChpID0gMDsgaSA8IG9iai5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgY2Fub25pY2FsaXplZE9ialtpXSA9IGNhbm9uaWNhbGl6ZShvYmpbaV0sIHN0YWNrLCByZXBsYWNlbWVudFN0YWNrLCByZXBsYWNlciwga2V5KTtcbiAgICB9XG4gICAgc3RhY2sucG9wKCk7XG4gICAgcmVwbGFjZW1lbnRTdGFjay5wb3AoKTtcbiAgICByZXR1cm4gY2Fub25pY2FsaXplZE9iajtcbiAgfVxuXG4gIGlmIChvYmogJiYgb2JqLnRvSlNPTikge1xuICAgIG9iaiA9IG9iai50b0pTT04oKTtcbiAgfVxuXG4gIGlmICh0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyAmJiBvYmogIT09IG51bGwpIHtcbiAgICBzdGFjay5wdXNoKG9iaik7XG4gICAgY2Fub25pY2FsaXplZE9iaiA9IHt9O1xuICAgIHJlcGxhY2VtZW50U3RhY2sucHVzaChjYW5vbmljYWxpemVkT2JqKTtcbiAgICBsZXQgc29ydGVkS2V5cyA9IFtdLFxuICAgICAgICBrZXk7XG4gICAgZm9yIChrZXkgaW4gb2JqKSB7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgaWYgKG9iai5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgIHNvcnRlZEtleXMucHVzaChrZXkpO1xuICAgICAgfVxuICAgIH1cbiAgICBzb3J0ZWRLZXlzLnNvcnQoKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgc29ydGVkS2V5cy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAga2V5ID0gc29ydGVkS2V5c1tpXTtcbiAgICAgIGNhbm9uaWNhbGl6ZWRPYmpba2V5XSA9IGNhbm9uaWNhbGl6ZShvYmpba2V5XSwgc3RhY2ssIHJlcGxhY2VtZW50U3RhY2ssIHJlcGxhY2VyLCBrZXkpO1xuICAgIH1cbiAgICBzdGFjay5wb3AoKTtcbiAgICByZXBsYWNlbWVudFN0YWNrLnBvcCgpO1xuICB9IGVsc2Uge1xuICAgIGNhbm9uaWNhbGl6ZWRPYmogPSBvYmo7XG4gIH1cbiAgcmV0dXJuIGNhbm9uaWNhbGl6ZWRPYmo7XG59XG4iXX0=
diff --git a/node_modules/libtap/node_modules/diff/lib/diff/line.js b/node_modules/libtap/node_modules/diff/lib/diff/line.js
new file mode 100644
index 0000000000000..f323f84a3a4ef
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/diff/line.js
@@ -0,0 +1,89 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.diffLines = diffLines;
+exports.diffTrimmedLines = diffTrimmedLines;
+exports.lineDiff = void 0;
+
+/*istanbul ignore end*/
+var
+/*istanbul ignore start*/
+_base = _interopRequireDefault(require("./base"))
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_params = require("../util/params")
+/*istanbul ignore end*/
+;
+
+/*istanbul ignore start*/ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/*istanbul ignore end*/
+var lineDiff = new
+/*istanbul ignore start*/
+_base
+/*istanbul ignore end*/
+.
+/*istanbul ignore start*/
+default
+/*istanbul ignore end*/
+();
+
+/*istanbul ignore start*/
+exports.lineDiff = lineDiff;
+
+/*istanbul ignore end*/
+lineDiff.tokenize = function (value) {
+  var retLines = [],
+      linesAndNewlines = value.split(/(\n|\r\n)/); // Ignore the final empty token that occurs if the string ends with a new line
+
+  if (!linesAndNewlines[linesAndNewlines.length - 1]) {
+    linesAndNewlines.pop();
+  } // Merge the content and line separators into single tokens
+
+
+  for (var i = 0; i < linesAndNewlines.length; i++) {
+    var line = linesAndNewlines[i];
+
+    if (i % 2 && !this.options.newlineIsToken) {
+      retLines[retLines.length - 1] += line;
+    } else {
+      if (this.options.ignoreWhitespace) {
+        line = line.trim();
+      }
+
+      retLines.push(line);
+    }
+  }
+
+  return retLines;
+};
+
+function diffLines(oldStr, newStr, callback) {
+  return lineDiff.diff(oldStr, newStr, callback);
+}
+
+function diffTrimmedLines(oldStr, newStr, callback) {
+  var options =
+  /*istanbul ignore start*/
+  (0,
+  /*istanbul ignore end*/
+
+  /*istanbul ignore start*/
+  _params
+  /*istanbul ignore end*/
+  .
+  /*istanbul ignore start*/
+  generateOptions)
+  /*istanbul ignore end*/
+  (callback, {
+    ignoreWhitespace: true
+  });
+  return lineDiff.diff(oldStr, newStr, options);
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2xpbmUuanMiXSwibmFtZXMiOlsibGluZURpZmYiLCJEaWZmIiwidG9rZW5pemUiLCJ2YWx1ZSIsInJldExpbmVzIiwibGluZXNBbmROZXdsaW5lcyIsInNwbGl0IiwibGVuZ3RoIiwicG9wIiwiaSIsImxpbmUiLCJvcHRpb25zIiwibmV3bGluZUlzVG9rZW4iLCJpZ25vcmVXaGl0ZXNwYWNlIiwidHJpbSIsInB1c2giLCJkaWZmTGluZXMiLCJvbGRTdHIiLCJuZXdTdHIiLCJjYWxsYmFjayIsImRpZmYiLCJkaWZmVHJpbW1lZExpbmVzIiwiZ2VuZXJhdGVPcHRpb25zIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7O0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTs7Ozs7QUFFTyxJQUFNQSxRQUFRLEdBQUc7QUFBSUM7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBSjtBQUFBLEVBQWpCOzs7Ozs7QUFDUEQsUUFBUSxDQUFDRSxRQUFULEdBQW9CLFVBQVNDLEtBQVQsRUFBZ0I7QUFDbEMsTUFBSUMsUUFBUSxHQUFHLEVBQWY7QUFBQSxNQUNJQyxnQkFBZ0IsR0FBR0YsS0FBSyxDQUFDRyxLQUFOLENBQVksV0FBWixDQUR2QixDQURrQyxDQUlsQzs7QUFDQSxNQUFJLENBQUNELGdCQUFnQixDQUFDQSxnQkFBZ0IsQ0FBQ0UsTUFBakIsR0FBMEIsQ0FBM0IsQ0FBckIsRUFBb0Q7QUFDbERGLElBQUFBLGdCQUFnQixDQUFDRyxHQUFqQjtBQUNELEdBUGlDLENBU2xDOzs7QUFDQSxPQUFLLElBQUlDLENBQUMsR0FBRyxDQUFiLEVBQWdCQSxDQUFDLEdBQUdKLGdCQUFnQixDQUFDRSxNQUFyQyxFQUE2Q0UsQ0FBQyxFQUE5QyxFQUFrRDtBQUNoRCxRQUFJQyxJQUFJLEdBQUdMLGdCQUFnQixDQUFDSSxDQUFELENBQTNCOztBQUVBLFFBQUlBLENBQUMsR0FBRyxDQUFKLElBQVMsQ0FBQyxLQUFLRSxPQUFMLENBQWFDLGNBQTNCLEVBQTJDO0FBQ3pDUixNQUFBQSxRQUFRLENBQUNBLFFBQVEsQ0FBQ0csTUFBVCxHQUFrQixDQUFuQixDQUFSLElBQWlDRyxJQUFqQztBQUNELEtBRkQsTUFFTztBQUNMLFVBQUksS0FBS0MsT0FBTCxDQUFhRSxnQkFBakIsRUFBbUM7QUFDakNILFFBQUFBLElBQUksR0FBR0EsSUFBSSxDQUFDSSxJQUFMLEVBQVA7QUFDRDs7QUFDRFYsTUFBQUEsUUFBUSxDQUFDVyxJQUFULENBQWNMLElBQWQ7QUFDRDtBQUNGOztBQUVELFNBQU9OLFFBQVA7QUFDRCxDQXhCRDs7QUEwQk8sU0FBU1ksU0FBVCxDQUFtQkMsTUFBbkIsRUFBMkJDLE1BQTNCLEVBQW1DQyxRQUFuQyxFQUE2QztBQUFFLFNBQU9uQixRQUFRLENBQUNvQixJQUFULENBQWNILE1BQWQsRUFBc0JDLE1BQXRCLEVBQThCQyxRQUE5QixDQUFQO0FBQWlEOztBQUNoRyxTQUFTRSxnQkFBVCxDQUEwQkosTUFBMUIsRUFBa0NDLE1BQWxDLEVBQTBDQyxRQUExQyxFQUFvRDtBQUN6RCxNQUFJUixPQUFPO0FBQUc7QUFBQTtBQUFBOztBQUFBVztBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBO0FBQUEsR0FBZ0JILFFBQWhCLEVBQTBCO0FBQUNOLElBQUFBLGdCQUFnQixFQUFFO0FBQW5CLEdBQTFCLENBQWQ7QUFDQSxTQUFPYixRQUFRLENBQUNvQixJQUFULENBQWNILE1BQWQsRUFBc0JDLE1BQXRCLEVBQThCUCxPQUE5QixDQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRGlmZiBmcm9tICcuL2Jhc2UnO1xuaW1wb3J0IHtnZW5lcmF0ZU9wdGlvbnN9IGZyb20gJy4uL3V0aWwvcGFyYW1zJztcblxuZXhwb3J0IGNvbnN0IGxpbmVEaWZmID0gbmV3IERpZmYoKTtcbmxpbmVEaWZmLnRva2VuaXplID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgbGV0IHJldExpbmVzID0gW10sXG4gICAgICBsaW5lc0FuZE5ld2xpbmVzID0gdmFsdWUuc3BsaXQoLyhcXG58XFxyXFxuKS8pO1xuXG4gIC8vIElnbm9yZSB0aGUgZmluYWwgZW1wdHkgdG9rZW4gdGhhdCBvY2N1cnMgaWYgdGhlIHN0cmluZyBlbmRzIHdpdGggYSBuZXcgbGluZVxuICBpZiAoIWxpbmVzQW5kTmV3bGluZXNbbGluZXNBbmROZXdsaW5lcy5sZW5ndGggLSAxXSkge1xuICAgIGxpbmVzQW5kTmV3bGluZXMucG9wKCk7XG4gIH1cblxuICAvLyBNZXJnZSB0aGUgY29udGVudCBhbmQgbGluZSBzZXBhcmF0b3JzIGludG8gc2luZ2xlIHRva2Vuc1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzQW5kTmV3bGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgbGluZSA9IGxpbmVzQW5kTmV3bGluZXNbaV07XG5cbiAgICBpZiAoaSAlIDIgJiYgIXRoaXMub3B0aW9ucy5uZXdsaW5lSXNUb2tlbikge1xuICAgICAgcmV0TGluZXNbcmV0TGluZXMubGVuZ3RoIC0gMV0gKz0gbGluZTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHRoaXMub3B0aW9ucy5pZ25vcmVXaGl0ZXNwYWNlKSB7XG4gICAgICAgIGxpbmUgPSBsaW5lLnRyaW0oKTtcbiAgICAgIH1cbiAgICAgIHJldExpbmVzLnB1c2gobGluZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldExpbmVzO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGRpZmZMaW5lcyhvbGRTdHIsIG5ld1N0ciwgY2FsbGJhY2spIHsgcmV0dXJuIGxpbmVEaWZmLmRpZmYob2xkU3RyLCBuZXdTdHIsIGNhbGxiYWNrKTsgfVxuZXhwb3J0IGZ1bmN0aW9uIGRpZmZUcmltbWVkTGluZXMob2xkU3RyLCBuZXdTdHIsIGNhbGxiYWNrKSB7XG4gIGxldCBvcHRpb25zID0gZ2VuZXJhdGVPcHRpb25zKGNhbGxiYWNrLCB7aWdub3JlV2hpdGVzcGFjZTogdHJ1ZX0pO1xuICByZXR1cm4gbGluZURpZmYuZGlmZihvbGRTdHIsIG5ld1N0ciwgb3B0aW9ucyk7XG59XG4iXX0=
diff --git a/node_modules/libtap/node_modules/diff/lib/diff/sentence.js b/node_modules/libtap/node_modules/diff/lib/diff/sentence.js
new file mode 100644
index 0000000000000..9ee96e962545e
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/diff/sentence.js
@@ -0,0 +1,41 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.diffSentences = diffSentences;
+exports.sentenceDiff = void 0;
+
+/*istanbul ignore end*/
+var
+/*istanbul ignore start*/
+_base = _interopRequireDefault(require("./base"))
+/*istanbul ignore end*/
+;
+
+/*istanbul ignore start*/ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/*istanbul ignore end*/
+var sentenceDiff = new
+/*istanbul ignore start*/
+_base
+/*istanbul ignore end*/
+.
+/*istanbul ignore start*/
+default
+/*istanbul ignore end*/
+();
+
+/*istanbul ignore start*/
+exports.sentenceDiff = sentenceDiff;
+
+/*istanbul ignore end*/
+sentenceDiff.tokenize = function (value) {
+  return value.split(/(\S.+?[.!?])(?=\s+|$)/);
+};
+
+function diffSentences(oldStr, newStr, callback) {
+  return sentenceDiff.diff(oldStr, newStr, callback);
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL3NlbnRlbmNlLmpzIl0sIm5hbWVzIjpbInNlbnRlbmNlRGlmZiIsIkRpZmYiLCJ0b2tlbml6ZSIsInZhbHVlIiwic3BsaXQiLCJkaWZmU2VudGVuY2VzIiwib2xkU3RyIiwibmV3U3RyIiwiY2FsbGJhY2siLCJkaWZmIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7Ozs7QUFHTyxJQUFNQSxZQUFZLEdBQUc7QUFBSUM7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBSjtBQUFBLEVBQXJCOzs7Ozs7QUFDUEQsWUFBWSxDQUFDRSxRQUFiLEdBQXdCLFVBQVNDLEtBQVQsRUFBZ0I7QUFDdEMsU0FBT0EsS0FBSyxDQUFDQyxLQUFOLENBQVksdUJBQVosQ0FBUDtBQUNELENBRkQ7O0FBSU8sU0FBU0MsYUFBVCxDQUF1QkMsTUFBdkIsRUFBK0JDLE1BQS9CLEVBQXVDQyxRQUF2QyxFQUFpRDtBQUFFLFNBQU9SLFlBQVksQ0FBQ1MsSUFBYixDQUFrQkgsTUFBbEIsRUFBMEJDLE1BQTFCLEVBQWtDQyxRQUFsQyxDQUFQO0FBQXFEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IERpZmYgZnJvbSAnLi9iYXNlJztcblxuXG5leHBvcnQgY29uc3Qgc2VudGVuY2VEaWZmID0gbmV3IERpZmYoKTtcbnNlbnRlbmNlRGlmZi50b2tlbml6ZSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZS5zcGxpdCgvKFxcUy4rP1suIT9dKSg/PVxccyt8JCkvKTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBkaWZmU2VudGVuY2VzKG9sZFN0ciwgbmV3U3RyLCBjYWxsYmFjaykgeyByZXR1cm4gc2VudGVuY2VEaWZmLmRpZmYob2xkU3RyLCBuZXdTdHIsIGNhbGxiYWNrKTsgfVxuIl19
diff --git a/node_modules/libtap/node_modules/diff/lib/diff/word.js b/node_modules/libtap/node_modules/diff/lib/diff/word.js
new file mode 100644
index 0000000000000..0b952e0748be8
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/diff/word.js
@@ -0,0 +1,107 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.diffWords = diffWords;
+exports.diffWordsWithSpace = diffWordsWithSpace;
+exports.wordDiff = void 0;
+
+/*istanbul ignore end*/
+var
+/*istanbul ignore start*/
+_base = _interopRequireDefault(require("./base"))
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_params = require("../util/params")
+/*istanbul ignore end*/
+;
+
+/*istanbul ignore start*/ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/*istanbul ignore end*/
+// Based on https://en.wikipedia.org/wiki/Latin_script_in_Unicode
+//
+// Ranges and exceptions:
+// Latin-1 Supplement, 0080–00FF
+//  - U+00D7  × Multiplication sign
+//  - U+00F7  ÷ Division sign
+// Latin Extended-A, 0100–017F
+// Latin Extended-B, 0180–024F
+// IPA Extensions, 0250–02AF
+// Spacing Modifier Letters, 02B0–02FF
+//  - U+02C7  ˇ ˇ  Caron
+//  - U+02D8  ˘ ˘  Breve
+//  - U+02D9  ˙ ˙  Dot Above
+//  - U+02DA  ˚ ˚  Ring Above
+//  - U+02DB  ˛ ˛  Ogonek
+//  - U+02DC  ˜ ˜  Small Tilde
+//  - U+02DD  ˝ ˝  Double Acute Accent
+// Latin Extended Additional, 1E00–1EFF
+var extendedWordChars = /^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/;
+var reWhitespace = /\S/;
+var wordDiff = new
+/*istanbul ignore start*/
+_base
+/*istanbul ignore end*/
+.
+/*istanbul ignore start*/
+default
+/*istanbul ignore end*/
+();
+
+/*istanbul ignore start*/
+exports.wordDiff = wordDiff;
+
+/*istanbul ignore end*/
+wordDiff.equals = function (left, right) {
+  if (this.options.ignoreCase) {
+    left = left.toLowerCase();
+    right = right.toLowerCase();
+  }
+
+  return left === right || this.options.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right);
+};
+
+wordDiff.tokenize = function (value) {
+  var tokens = value.split(/(\s+|[()[\]{}'"]|\b)/); // Join the boundary splits that we do not consider to be boundaries. This is primarily the extended Latin character set.
+
+  for (var i = 0; i < tokens.length - 1; i++) {
+    // If we have an empty string in the next field and we have only word chars before and after, merge
+    if (!tokens[i + 1] && tokens[i + 2] && extendedWordChars.test(tokens[i]) && extendedWordChars.test(tokens[i + 2])) {
+      tokens[i] += tokens[i + 2];
+      tokens.splice(i + 1, 2);
+      i--;
+    }
+  }
+
+  return tokens;
+};
+
+function diffWords(oldStr, newStr, options) {
+  options =
+  /*istanbul ignore start*/
+  (0,
+  /*istanbul ignore end*/
+
+  /*istanbul ignore start*/
+  _params
+  /*istanbul ignore end*/
+  .
+  /*istanbul ignore start*/
+  generateOptions)
+  /*istanbul ignore end*/
+  (options, {
+    ignoreWhitespace: true
+  });
+  return wordDiff.diff(oldStr, newStr, options);
+}
+
+function diffWordsWithSpace(oldStr, newStr, options) {
+  return wordDiff.diff(oldStr, newStr, options);
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL3dvcmQuanMiXSwibmFtZXMiOlsiZXh0ZW5kZWRXb3JkQ2hhcnMiLCJyZVdoaXRlc3BhY2UiLCJ3b3JkRGlmZiIsIkRpZmYiLCJlcXVhbHMiLCJsZWZ0IiwicmlnaHQiLCJvcHRpb25zIiwiaWdub3JlQ2FzZSIsInRvTG93ZXJDYXNlIiwiaWdub3JlV2hpdGVzcGFjZSIsInRlc3QiLCJ0b2tlbml6ZSIsInZhbHVlIiwidG9rZW5zIiwic3BsaXQiLCJpIiwibGVuZ3RoIiwic3BsaWNlIiwiZGlmZldvcmRzIiwib2xkU3RyIiwibmV3U3RyIiwiZ2VuZXJhdGVPcHRpb25zIiwiZGlmZiIsImRpZmZXb3Jkc1dpdGhTcGFjZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOztBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7Ozs7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBTUEsaUJBQWlCLEdBQUcsK0RBQTFCO0FBRUEsSUFBTUMsWUFBWSxHQUFHLElBQXJCO0FBRU8sSUFBTUMsUUFBUSxHQUFHO0FBQUlDO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUo7QUFBQSxFQUFqQjs7Ozs7O0FBQ1BELFFBQVEsQ0FBQ0UsTUFBVCxHQUFrQixVQUFTQyxJQUFULEVBQWVDLEtBQWYsRUFBc0I7QUFDdEMsTUFBSSxLQUFLQyxPQUFMLENBQWFDLFVBQWpCLEVBQTZCO0FBQzNCSCxJQUFBQSxJQUFJLEdBQUdBLElBQUksQ0FBQ0ksV0FBTCxFQUFQO0FBQ0FILElBQUFBLEtBQUssR0FBR0EsS0FBSyxDQUFDRyxXQUFOLEVBQVI7QUFDRDs7QUFDRCxTQUFPSixJQUFJLEtBQUtDLEtBQVQsSUFBbUIsS0FBS0MsT0FBTCxDQUFhRyxnQkFBYixJQUFpQyxDQUFDVCxZQUFZLENBQUNVLElBQWIsQ0FBa0JOLElBQWxCLENBQWxDLElBQTZELENBQUNKLFlBQVksQ0FBQ1UsSUFBYixDQUFrQkwsS0FBbEIsQ0FBeEY7QUFDRCxDQU5EOztBQU9BSixRQUFRLENBQUNVLFFBQVQsR0FBb0IsVUFBU0MsS0FBVCxFQUFnQjtBQUNsQyxNQUFJQyxNQUFNLEdBQUdELEtBQUssQ0FBQ0UsS0FBTixDQUFZLHNCQUFaLENBQWIsQ0FEa0MsQ0FHbEM7O0FBQ0EsT0FBSyxJQUFJQyxDQUFDLEdBQUcsQ0FBYixFQUFnQkEsQ0FBQyxHQUFHRixNQUFNLENBQUNHLE1BQVAsR0FBZ0IsQ0FBcEMsRUFBdUNELENBQUMsRUFBeEMsRUFBNEM7QUFDMUM7QUFDQSxRQUFJLENBQUNGLE1BQU0sQ0FBQ0UsQ0FBQyxHQUFHLENBQUwsQ0FBUCxJQUFrQkYsTUFBTSxDQUFDRSxDQUFDLEdBQUcsQ0FBTCxDQUF4QixJQUNLaEIsaUJBQWlCLENBQUNXLElBQWxCLENBQXVCRyxNQUFNLENBQUNFLENBQUQsQ0FBN0IsQ0FETCxJQUVLaEIsaUJBQWlCLENBQUNXLElBQWxCLENBQXVCRyxNQUFNLENBQUNFLENBQUMsR0FBRyxDQUFMLENBQTdCLENBRlQsRUFFZ0Q7QUFDOUNGLE1BQUFBLE1BQU0sQ0FBQ0UsQ0FBRCxDQUFOLElBQWFGLE1BQU0sQ0FBQ0UsQ0FBQyxHQUFHLENBQUwsQ0FBbkI7QUFDQUYsTUFBQUEsTUFBTSxDQUFDSSxNQUFQLENBQWNGLENBQUMsR0FBRyxDQUFsQixFQUFxQixDQUFyQjtBQUNBQSxNQUFBQSxDQUFDO0FBQ0Y7QUFDRjs7QUFFRCxTQUFPRixNQUFQO0FBQ0QsQ0FoQkQ7O0FBa0JPLFNBQVNLLFNBQVQsQ0FBbUJDLE1BQW5CLEVBQTJCQyxNQUEzQixFQUFtQ2QsT0FBbkMsRUFBNEM7QUFDakRBLEVBQUFBLE9BQU87QUFBRztBQUFBO0FBQUE7O0FBQUFlO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUE7QUFBQSxHQUFnQmYsT0FBaEIsRUFBeUI7QUFBQ0csSUFBQUEsZ0JBQWdCLEVBQUU7QUFBbkIsR0FBekIsQ0FBVjtBQUNBLFNBQU9SLFFBQVEsQ0FBQ3FCLElBQVQsQ0FBY0gsTUFBZCxFQUFzQkMsTUFBdEIsRUFBOEJkLE9BQTlCLENBQVA7QUFDRDs7QUFFTSxTQUFTaUIsa0JBQVQsQ0FBNEJKLE1BQTVCLEVBQW9DQyxNQUFwQyxFQUE0Q2QsT0FBNUMsRUFBcUQ7QUFDMUQsU0FBT0wsUUFBUSxDQUFDcUIsSUFBVCxDQUFjSCxNQUFkLEVBQXNCQyxNQUF0QixFQUE4QmQsT0FBOUIsQ0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IERpZmYgZnJvbSAnLi9iYXNlJztcbmltcG9ydCB7Z2VuZXJhdGVPcHRpb25zfSBmcm9tICcuLi91dGlsL3BhcmFtcyc7XG5cbi8vIEJhc2VkIG9uIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0xhdGluX3NjcmlwdF9pbl9Vbmljb2RlXG4vL1xuLy8gUmFuZ2VzIGFuZCBleGNlcHRpb25zOlxuLy8gTGF0aW4tMSBTdXBwbGVtZW50LCAwMDgw4oCTMDBGRlxuLy8gIC0gVSswMEQ3ICDDlyBNdWx0aXBsaWNhdGlvbiBzaWduXG4vLyAgLSBVKzAwRjcgIMO3IERpdmlzaW9uIHNpZ25cbi8vIExhdGluIEV4dGVuZGVkLUEsIDAxMDDigJMwMTdGXG4vLyBMYXRpbiBFeHRlbmRlZC1CLCAwMTgw4oCTMDI0RlxuLy8gSVBBIEV4dGVuc2lvbnMsIDAyNTDigJMwMkFGXG4vLyBTcGFjaW5nIE1vZGlmaWVyIExldHRlcnMsIDAyQjDigJMwMkZGXG4vLyAgLSBVKzAyQzcgIMuHICYjNzExOyAgQ2Fyb25cbi8vICAtIFUrMDJEOCAgy5ggJiM3Mjg7ICBCcmV2ZVxuLy8gIC0gVSswMkQ5ICDLmSAmIzcyOTsgIERvdCBBYm92ZVxuLy8gIC0gVSswMkRBICDLmiAmIzczMDsgIFJpbmcgQWJvdmVcbi8vICAtIFUrMDJEQiAgy5sgJiM3MzE7ICBPZ29uZWtcbi8vICAtIFUrMDJEQyAgy5wgJiM3MzI7ICBTbWFsbCBUaWxkZVxuLy8gIC0gVSswMkREICDLnSAmIzczMzsgIERvdWJsZSBBY3V0ZSBBY2NlbnRcbi8vIExhdGluIEV4dGVuZGVkIEFkZGl0aW9uYWwsIDFFMDDigJMxRUZGXG5jb25zdCBleHRlbmRlZFdvcmRDaGFycyA9IC9eW2EtekEtWlxcdXtDMH0tXFx1e0ZGfVxcdXtEOH0tXFx1e0Y2fVxcdXtGOH0tXFx1ezJDNn1cXHV7MkM4fS1cXHV7MkQ3fVxcdXsyREV9LVxcdXsyRkZ9XFx1ezFFMDB9LVxcdXsxRUZGfV0rJC91O1xuXG5jb25zdCByZVdoaXRlc3BhY2UgPSAvXFxTLztcblxuZXhwb3J0IGNvbnN0IHdvcmREaWZmID0gbmV3IERpZmYoKTtcbndvcmREaWZmLmVxdWFscyA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7XG4gIGlmICh0aGlzLm9wdGlvbnMuaWdub3JlQ2FzZSkge1xuICAgIGxlZnQgPSBsZWZ0LnRvTG93ZXJDYXNlKCk7XG4gICAgcmlnaHQgPSByaWdodC50b0xvd2VyQ2FzZSgpO1xuICB9XG4gIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCAodGhpcy5vcHRpb25zLmlnbm9yZVdoaXRlc3BhY2UgJiYgIXJlV2hpdGVzcGFjZS50ZXN0KGxlZnQpICYmICFyZVdoaXRlc3BhY2UudGVzdChyaWdodCkpO1xufTtcbndvcmREaWZmLnRva2VuaXplID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgbGV0IHRva2VucyA9IHZhbHVlLnNwbGl0KC8oXFxzK3xbKClbXFxde30nXCJdfFxcYikvKTtcblxuICAvLyBKb2luIHRoZSBib3VuZGFyeSBzcGxpdHMgdGhhdCB3ZSBkbyBub3QgY29uc2lkZXIgdG8gYmUgYm91bmRhcmllcy4gVGhpcyBpcyBwcmltYXJpbHkgdGhlIGV4dGVuZGVkIExhdGluIGNoYXJhY3RlciBzZXQuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgdG9rZW5zLmxlbmd0aCAtIDE7IGkrKykge1xuICAgIC8vIElmIHdlIGhhdmUgYW4gZW1wdHkgc3RyaW5nIGluIHRoZSBuZXh0IGZpZWxkIGFuZCB3ZSBoYXZlIG9ubHkgd29yZCBjaGFycyBiZWZvcmUgYW5kIGFmdGVyLCBtZXJnZVxuICAgIGlmICghdG9rZW5zW2kgKyAxXSAmJiB0b2tlbnNbaSArIDJdXG4gICAgICAgICAgJiYgZXh0ZW5kZWRXb3JkQ2hhcnMudGVzdCh0b2tlbnNbaV0pXG4gICAgICAgICAgJiYgZXh0ZW5kZWRXb3JkQ2hhcnMudGVzdCh0b2tlbnNbaSArIDJdKSkge1xuICAgICAgdG9rZW5zW2ldICs9IHRva2Vuc1tpICsgMl07XG4gICAgICB0b2tlbnMuc3BsaWNlKGkgKyAxLCAyKTtcbiAgICAgIGktLTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdG9rZW5zO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGRpZmZXb3JkcyhvbGRTdHIsIG5ld1N0ciwgb3B0aW9ucykge1xuICBvcHRpb25zID0gZ2VuZXJhdGVPcHRpb25zKG9wdGlvbnMsIHtpZ25vcmVXaGl0ZXNwYWNlOiB0cnVlfSk7XG4gIHJldHVybiB3b3JkRGlmZi5kaWZmKG9sZFN0ciwgbmV3U3RyLCBvcHRpb25zKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRpZmZXb3Jkc1dpdGhTcGFjZShvbGRTdHIsIG5ld1N0ciwgb3B0aW9ucykge1xuICByZXR1cm4gd29yZERpZmYuZGlmZihvbGRTdHIsIG5ld1N0ciwgb3B0aW9ucyk7XG59XG4iXX0=
diff --git a/node_modules/libtap/node_modules/diff/lib/index.es6.js b/node_modules/libtap/node_modules/diff/lib/index.es6.js
new file mode 100644
index 0000000000000..b6458430d7906
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/index.es6.js
@@ -0,0 +1,1519 @@
+function Diff() {}
+Diff.prototype = {
+  diff: function diff(oldString, newString) {
+    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
+    var callback = options.callback;
+
+    if (typeof options === 'function') {
+      callback = options;
+      options = {};
+    }
+
+    this.options = options;
+    var self = this;
+
+    function done(value) {
+      if (callback) {
+        setTimeout(function () {
+          callback(undefined, value);
+        }, 0);
+        return true;
+      } else {
+        return value;
+      }
+    } // Allow subclasses to massage the input prior to running
+
+
+    oldString = this.castInput(oldString);
+    newString = this.castInput(newString);
+    oldString = this.removeEmpty(this.tokenize(oldString));
+    newString = this.removeEmpty(this.tokenize(newString));
+    var newLen = newString.length,
+        oldLen = oldString.length;
+    var editLength = 1;
+    var maxEditLength = newLen + oldLen;
+    var bestPath = [{
+      newPos: -1,
+      components: []
+    }]; // Seed editLength = 0, i.e. the content starts with the same values
+
+    var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
+
+    if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
+      // Identity per the equality and tokenizer
+      return done([{
+        value: this.join(newString),
+        count: newString.length
+      }]);
+    } // Main worker method. checks all permutations of a given edit length for acceptance.
+
+
+    function execEditLength() {
+      for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) {
+        var basePath = void 0;
+
+        var addPath = bestPath[diagonalPath - 1],
+            removePath = bestPath[diagonalPath + 1],
+            _oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
+
+        if (addPath) {
+          // No one else is going to attempt to use this value, clear it
+          bestPath[diagonalPath - 1] = undefined;
+        }
+
+        var canAdd = addPath && addPath.newPos + 1 < newLen,
+            canRemove = removePath && 0 <= _oldPos && _oldPos < oldLen;
+
+        if (!canAdd && !canRemove) {
+          // If this path is a terminal then prune
+          bestPath[diagonalPath] = undefined;
+          continue;
+        } // Select the diagonal that we want to branch from. We select the prior
+        // path whose position in the new string is the farthest from the origin
+        // and does not pass the bounds of the diff graph
+
+
+        if (!canAdd || canRemove && addPath.newPos < removePath.newPos) {
+          basePath = clonePath(removePath);
+          self.pushComponent(basePath.components, undefined, true);
+        } else {
+          basePath = addPath; // No need to clone, we've pulled it from the list
+
+          basePath.newPos++;
+          self.pushComponent(basePath.components, true, undefined);
+        }
+
+        _oldPos = self.extractCommon(basePath, newString, oldString, diagonalPath); // If we have hit the end of both strings, then we are done
+
+        if (basePath.newPos + 1 >= newLen && _oldPos + 1 >= oldLen) {
+          return done(buildValues(self, basePath.components, newString, oldString, self.useLongestToken));
+        } else {
+          // Otherwise track this path as a potential candidate and continue.
+          bestPath[diagonalPath] = basePath;
+        }
+      }
+
+      editLength++;
+    } // Performs the length of edit iteration. Is a bit fugly as this has to support the
+    // sync and async mode which is never fun. Loops over execEditLength until a value
+    // is produced.
+
+
+    if (callback) {
+      (function exec() {
+        setTimeout(function () {
+          // This should not happen, but we want to be safe.
+
+          /* istanbul ignore next */
+          if (editLength > maxEditLength) {
+            return callback();
+          }
+
+          if (!execEditLength()) {
+            exec();
+          }
+        }, 0);
+      })();
+    } else {
+      while (editLength <= maxEditLength) {
+        var ret = execEditLength();
+
+        if (ret) {
+          return ret;
+        }
+      }
+    }
+  },
+  pushComponent: function pushComponent(components, added, removed) {
+    var last = components[components.length - 1];
+
+    if (last && last.added === added && last.removed === removed) {
+      // We need to clone here as the component clone operation is just
+      // as shallow array clone
+      components[components.length - 1] = {
+        count: last.count + 1,
+        added: added,
+        removed: removed
+      };
+    } else {
+      components.push({
+        count: 1,
+        added: added,
+        removed: removed
+      });
+    }
+  },
+  extractCommon: function extractCommon(basePath, newString, oldString, diagonalPath) {
+    var newLen = newString.length,
+        oldLen = oldString.length,
+        newPos = basePath.newPos,
+        oldPos = newPos - diagonalPath,
+        commonCount = 0;
+
+    while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) {
+      newPos++;
+      oldPos++;
+      commonCount++;
+    }
+
+    if (commonCount) {
+      basePath.components.push({
+        count: commonCount
+      });
+    }
+
+    basePath.newPos = newPos;
+    return oldPos;
+  },
+  equals: function equals(left, right) {
+    if (this.options.comparator) {
+      return this.options.comparator(left, right);
+    } else {
+      return left === right || this.options.ignoreCase && left.toLowerCase() === right.toLowerCase();
+    }
+  },
+  removeEmpty: function removeEmpty(array) {
+    var ret = [];
+
+    for (var i = 0; i < array.length; i++) {
+      if (array[i]) {
+        ret.push(array[i]);
+      }
+    }
+
+    return ret;
+  },
+  castInput: function castInput(value) {
+    return value;
+  },
+  tokenize: function tokenize(value) {
+    return value.split('');
+  },
+  join: function join(chars) {
+    return chars.join('');
+  }
+};
+
+function buildValues(diff, components, newString, oldString, useLongestToken) {
+  var componentPos = 0,
+      componentLen = components.length,
+      newPos = 0,
+      oldPos = 0;
+
+  for (; componentPos < componentLen; componentPos++) {
+    var component = components[componentPos];
+
+    if (!component.removed) {
+      if (!component.added && useLongestToken) {
+        var value = newString.slice(newPos, newPos + component.count);
+        value = value.map(function (value, i) {
+          var oldValue = oldString[oldPos + i];
+          return oldValue.length > value.length ? oldValue : value;
+        });
+        component.value = diff.join(value);
+      } else {
+        component.value = diff.join(newString.slice(newPos, newPos + component.count));
+      }
+
+      newPos += component.count; // Common case
+
+      if (!component.added) {
+        oldPos += component.count;
+      }
+    } else {
+      component.value = diff.join(oldString.slice(oldPos, oldPos + component.count));
+      oldPos += component.count; // Reverse add and remove so removes are output first to match common convention
+      // The diffing algorithm is tied to add then remove output and this is the simplest
+      // route to get the desired output with minimal overhead.
+
+      if (componentPos && components[componentPos - 1].added) {
+        var tmp = components[componentPos - 1];
+        components[componentPos - 1] = components[componentPos];
+        components[componentPos] = tmp;
+      }
+    }
+  } // Special case handle for when one terminal is ignored (i.e. whitespace).
+  // For this case we merge the terminal into the prior string and drop the change.
+  // This is only available for string mode.
+
+
+  var lastComponent = components[componentLen - 1];
+
+  if (componentLen > 1 && typeof lastComponent.value === 'string' && (lastComponent.added || lastComponent.removed) && diff.equals('', lastComponent.value)) {
+    components[componentLen - 2].value += lastComponent.value;
+    components.pop();
+  }
+
+  return components;
+}
+
+function clonePath(path) {
+  return {
+    newPos: path.newPos,
+    components: path.components.slice(0)
+  };
+}
+
+var characterDiff = new Diff();
+function diffChars(oldStr, newStr, options) {
+  return characterDiff.diff(oldStr, newStr, options);
+}
+
+function generateOptions(options, defaults) {
+  if (typeof options === 'function') {
+    defaults.callback = options;
+  } else if (options) {
+    for (var name in options) {
+      /* istanbul ignore else */
+      if (options.hasOwnProperty(name)) {
+        defaults[name] = options[name];
+      }
+    }
+  }
+
+  return defaults;
+}
+
+//
+// Ranges and exceptions:
+// Latin-1 Supplement, 0080–00FF
+//  - U+00D7  × Multiplication sign
+//  - U+00F7  ÷ Division sign
+// Latin Extended-A, 0100–017F
+// Latin Extended-B, 0180–024F
+// IPA Extensions, 0250–02AF
+// Spacing Modifier Letters, 02B0–02FF
+//  - U+02C7  ˇ ˇ  Caron
+//  - U+02D8  ˘ ˘  Breve
+//  - U+02D9  ˙ ˙  Dot Above
+//  - U+02DA  ˚ ˚  Ring Above
+//  - U+02DB  ˛ ˛  Ogonek
+//  - U+02DC  ˜ ˜  Small Tilde
+//  - U+02DD  ˝ ˝  Double Acute Accent
+// Latin Extended Additional, 1E00–1EFF
+
+var extendedWordChars = /^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/;
+var reWhitespace = /\S/;
+var wordDiff = new Diff();
+
+wordDiff.equals = function (left, right) {
+  if (this.options.ignoreCase) {
+    left = left.toLowerCase();
+    right = right.toLowerCase();
+  }
+
+  return left === right || this.options.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right);
+};
+
+wordDiff.tokenize = function (value) {
+  var tokens = value.split(/(\s+|[()[\]{}'"]|\b)/); // Join the boundary splits that we do not consider to be boundaries. This is primarily the extended Latin character set.
+
+  for (var i = 0; i < tokens.length - 1; i++) {
+    // If we have an empty string in the next field and we have only word chars before and after, merge
+    if (!tokens[i + 1] && tokens[i + 2] && extendedWordChars.test(tokens[i]) && extendedWordChars.test(tokens[i + 2])) {
+      tokens[i] += tokens[i + 2];
+      tokens.splice(i + 1, 2);
+      i--;
+    }
+  }
+
+  return tokens;
+};
+
+function diffWords(oldStr, newStr, options) {
+  options = generateOptions(options, {
+    ignoreWhitespace: true
+  });
+  return wordDiff.diff(oldStr, newStr, options);
+}
+function diffWordsWithSpace(oldStr, newStr, options) {
+  return wordDiff.diff(oldStr, newStr, options);
+}
+
+var lineDiff = new Diff();
+
+lineDiff.tokenize = function (value) {
+  var retLines = [],
+      linesAndNewlines = value.split(/(\n|\r\n)/); // Ignore the final empty token that occurs if the string ends with a new line
+
+  if (!linesAndNewlines[linesAndNewlines.length - 1]) {
+    linesAndNewlines.pop();
+  } // Merge the content and line separators into single tokens
+
+
+  for (var i = 0; i < linesAndNewlines.length; i++) {
+    var line = linesAndNewlines[i];
+
+    if (i % 2 && !this.options.newlineIsToken) {
+      retLines[retLines.length - 1] += line;
+    } else {
+      if (this.options.ignoreWhitespace) {
+        line = line.trim();
+      }
+
+      retLines.push(line);
+    }
+  }
+
+  return retLines;
+};
+
+function diffLines(oldStr, newStr, callback) {
+  return lineDiff.diff(oldStr, newStr, callback);
+}
+function diffTrimmedLines(oldStr, newStr, callback) {
+  var options = generateOptions(callback, {
+    ignoreWhitespace: true
+  });
+  return lineDiff.diff(oldStr, newStr, options);
+}
+
+var sentenceDiff = new Diff();
+
+sentenceDiff.tokenize = function (value) {
+  return value.split(/(\S.+?[.!?])(?=\s+|$)/);
+};
+
+function diffSentences(oldStr, newStr, callback) {
+  return sentenceDiff.diff(oldStr, newStr, callback);
+}
+
+var cssDiff = new Diff();
+
+cssDiff.tokenize = function (value) {
+  return value.split(/([{}:;,]|\s+)/);
+};
+
+function diffCss(oldStr, newStr, callback) {
+  return cssDiff.diff(oldStr, newStr, callback);
+}
+
+function _typeof(obj) {
+  if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
+    _typeof = function (obj) {
+      return typeof obj;
+    };
+  } else {
+    _typeof = function (obj) {
+      return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
+    };
+  }
+
+  return _typeof(obj);
+}
+
+function _toConsumableArray(arr) {
+  return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
+}
+
+function _arrayWithoutHoles(arr) {
+  if (Array.isArray(arr)) {
+    for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
+
+    return arr2;
+  }
+}
+
+function _iterableToArray(iter) {
+  if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
+}
+
+function _nonIterableSpread() {
+  throw new TypeError("Invalid attempt to spread non-iterable instance");
+}
+
+var objectPrototypeToString = Object.prototype.toString;
+var jsonDiff = new Diff(); // Discriminate between two lines of pretty-printed, serialized JSON where one of them has a
+// dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output:
+
+jsonDiff.useLongestToken = true;
+jsonDiff.tokenize = lineDiff.tokenize;
+
+jsonDiff.castInput = function (value) {
+  var _this$options = this.options,
+      undefinedReplacement = _this$options.undefinedReplacement,
+      _this$options$stringi = _this$options.stringifyReplacer,
+      stringifyReplacer = _this$options$stringi === void 0 ? function (k, v) {
+    return typeof v === 'undefined' ? undefinedReplacement : v;
+  } : _this$options$stringi;
+  return typeof value === 'string' ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), stringifyReplacer, '  ');
+};
+
+jsonDiff.equals = function (left, right) {
+  return Diff.prototype.equals.call(jsonDiff, left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1'));
+};
+
+function diffJson(oldObj, newObj, options) {
+  return jsonDiff.diff(oldObj, newObj, options);
+} // This function handles the presence of circular references by bailing out when encountering an
+// object that is already on the "stack" of items being processed. Accepts an optional replacer
+
+function canonicalize(obj, stack, replacementStack, replacer, key) {
+  stack = stack || [];
+  replacementStack = replacementStack || [];
+
+  if (replacer) {
+    obj = replacer(key, obj);
+  }
+
+  var i;
+
+  for (i = 0; i < stack.length; i += 1) {
+    if (stack[i] === obj) {
+      return replacementStack[i];
+    }
+  }
+
+  var canonicalizedObj;
+
+  if ('[object Array]' === objectPrototypeToString.call(obj)) {
+    stack.push(obj);
+    canonicalizedObj = new Array(obj.length);
+    replacementStack.push(canonicalizedObj);
+
+    for (i = 0; i < obj.length; i += 1) {
+      canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack, replacer, key);
+    }
+
+    stack.pop();
+    replacementStack.pop();
+    return canonicalizedObj;
+  }
+
+  if (obj && obj.toJSON) {
+    obj = obj.toJSON();
+  }
+
+  if (_typeof(obj) === 'object' && obj !== null) {
+    stack.push(obj);
+    canonicalizedObj = {};
+    replacementStack.push(canonicalizedObj);
+
+    var sortedKeys = [],
+        _key;
+
+    for (_key in obj) {
+      /* istanbul ignore else */
+      if (obj.hasOwnProperty(_key)) {
+        sortedKeys.push(_key);
+      }
+    }
+
+    sortedKeys.sort();
+
+    for (i = 0; i < sortedKeys.length; i += 1) {
+      _key = sortedKeys[i];
+      canonicalizedObj[_key] = canonicalize(obj[_key], stack, replacementStack, replacer, _key);
+    }
+
+    stack.pop();
+    replacementStack.pop();
+  } else {
+    canonicalizedObj = obj;
+  }
+
+  return canonicalizedObj;
+}
+
+var arrayDiff = new Diff();
+
+arrayDiff.tokenize = function (value) {
+  return value.slice();
+};
+
+arrayDiff.join = arrayDiff.removeEmpty = function (value) {
+  return value;
+};
+
+function diffArrays(oldArr, newArr, callback) {
+  return arrayDiff.diff(oldArr, newArr, callback);
+}
+
+function parsePatch(uniDiff) {
+  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+  var diffstr = uniDiff.split(/\r\n|[\n\v\f\r\x85]/),
+      delimiters = uniDiff.match(/\r\n|[\n\v\f\r\x85]/g) || [],
+      list = [],
+      i = 0;
+
+  function parseIndex() {
+    var index = {};
+    list.push(index); // Parse diff metadata
+
+    while (i < diffstr.length) {
+      var line = diffstr[i]; // File header found, end parsing diff metadata
+
+      if (/^(\-\-\-|\+\+\+|@@)\s/.test(line)) {
+        break;
+      } // Diff index
+
+
+      var header = /^(?:Index:|diff(?: -r \w+)+)\s+(.+?)\s*$/.exec(line);
+
+      if (header) {
+        index.index = header[1];
+      }
+
+      i++;
+    } // Parse file headers if they are defined. Unified diff requires them, but
+    // there's no technical issues to have an isolated hunk without file header
+
+
+    parseFileHeader(index);
+    parseFileHeader(index); // Parse hunks
+
+    index.hunks = [];
+
+    while (i < diffstr.length) {
+      var _line = diffstr[i];
+
+      if (/^(Index:|diff|\-\-\-|\+\+\+)\s/.test(_line)) {
+        break;
+      } else if (/^@@/.test(_line)) {
+        index.hunks.push(parseHunk());
+      } else if (_line && options.strict) {
+        // Ignore unexpected content unless in strict mode
+        throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(_line));
+      } else {
+        i++;
+      }
+    }
+  } // Parses the --- and +++ headers, if none are found, no lines
+  // are consumed.
+
+
+  function parseFileHeader(index) {
+    var fileHeader = /^(---|\+\+\+)\s+(.*)$/.exec(diffstr[i]);
+
+    if (fileHeader) {
+      var keyPrefix = fileHeader[1] === '---' ? 'old' : 'new';
+      var data = fileHeader[2].split('\t', 2);
+      var fileName = data[0].replace(/\\\\/g, '\\');
+
+      if (/^".*"$/.test(fileName)) {
+        fileName = fileName.substr(1, fileName.length - 2);
+      }
+
+      index[keyPrefix + 'FileName'] = fileName;
+      index[keyPrefix + 'Header'] = (data[1] || '').trim();
+      i++;
+    }
+  } // Parses a hunk
+  // This assumes that we are at the start of a hunk.
+
+
+  function parseHunk() {
+    var chunkHeaderIndex = i,
+        chunkHeaderLine = diffstr[i++],
+        chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
+    var hunk = {
+      oldStart: +chunkHeader[1],
+      oldLines: +chunkHeader[2] || 1,
+      newStart: +chunkHeader[3],
+      newLines: +chunkHeader[4] || 1,
+      lines: [],
+      linedelimiters: []
+    };
+    var addCount = 0,
+        removeCount = 0;
+
+    for (; i < diffstr.length; i++) {
+      // Lines starting with '---' could be mistaken for the "remove line" operation
+      // But they could be the header for the next file. Therefore prune such cases out.
+      if (diffstr[i].indexOf('--- ') === 0 && i + 2 < diffstr.length && diffstr[i + 1].indexOf('+++ ') === 0 && diffstr[i + 2].indexOf('@@') === 0) {
+        break;
+      }
+
+      var operation = diffstr[i].length == 0 && i != diffstr.length - 1 ? ' ' : diffstr[i][0];
+
+      if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') {
+        hunk.lines.push(diffstr[i]);
+        hunk.linedelimiters.push(delimiters[i] || '\n');
+
+        if (operation === '+') {
+          addCount++;
+        } else if (operation === '-') {
+          removeCount++;
+        } else if (operation === ' ') {
+          addCount++;
+          removeCount++;
+        }
+      } else {
+        break;
+      }
+    } // Handle the empty block count case
+
+
+    if (!addCount && hunk.newLines === 1) {
+      hunk.newLines = 0;
+    }
+
+    if (!removeCount && hunk.oldLines === 1) {
+      hunk.oldLines = 0;
+    } // Perform optional sanity checking
+
+
+    if (options.strict) {
+      if (addCount !== hunk.newLines) {
+        throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
+      }
+
+      if (removeCount !== hunk.oldLines) {
+        throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
+      }
+    }
+
+    return hunk;
+  }
+
+  while (i < diffstr.length) {
+    parseIndex();
+  }
+
+  return list;
+}
+
+// Iterator that traverses in the range of [min, max], stepping
+// by distance from a given start position. I.e. for [0, 4], with
+// start of 2, this will iterate 2, 3, 1, 4, 0.
+function distanceIterator (start, minLine, maxLine) {
+  var wantForward = true,
+      backwardExhausted = false,
+      forwardExhausted = false,
+      localOffset = 1;
+  return function iterator() {
+    if (wantForward && !forwardExhausted) {
+      if (backwardExhausted) {
+        localOffset++;
+      } else {
+        wantForward = false;
+      } // Check if trying to fit beyond text length, and if not, check it fits
+      // after offset location (or desired location on first iteration)
+
+
+      if (start + localOffset <= maxLine) {
+        return localOffset;
+      }
+
+      forwardExhausted = true;
+    }
+
+    if (!backwardExhausted) {
+      if (!forwardExhausted) {
+        wantForward = true;
+      } // Check if trying to fit before text beginning, and if not, check it fits
+      // before offset location
+
+
+      if (minLine <= start - localOffset) {
+        return -localOffset++;
+      }
+
+      backwardExhausted = true;
+      return iterator();
+    } // We tried to fit hunk before text beginning and beyond text length, then
+    // hunk can't fit on the text. Return undefined
+
+  };
+}
+
+function applyPatch(source, uniDiff) {
+  var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
+
+  if (typeof uniDiff === 'string') {
+    uniDiff = parsePatch(uniDiff);
+  }
+
+  if (Array.isArray(uniDiff)) {
+    if (uniDiff.length > 1) {
+      throw new Error('applyPatch only works with a single input.');
+    }
+
+    uniDiff = uniDiff[0];
+  } // Apply the diff to the input
+
+
+  var lines = source.split(/\r\n|[\n\v\f\r\x85]/),
+      delimiters = source.match(/\r\n|[\n\v\f\r\x85]/g) || [],
+      hunks = uniDiff.hunks,
+      compareLine = options.compareLine || function (lineNumber, line, operation, patchContent) {
+    return line === patchContent;
+  },
+      errorCount = 0,
+      fuzzFactor = options.fuzzFactor || 0,
+      minLine = 0,
+      offset = 0,
+      removeEOFNL,
+      addEOFNL;
+  /**
+   * Checks if the hunk exactly fits on the provided location
+   */
+
+
+  function hunkFits(hunk, toPos) {
+    for (var j = 0; j < hunk.lines.length; j++) {
+      var line = hunk.lines[j],
+          operation = line.length > 0 ? line[0] : ' ',
+          content = line.length > 0 ? line.substr(1) : line;
+
+      if (operation === ' ' || operation === '-') {
+        // Context sanity check
+        if (!compareLine(toPos + 1, lines[toPos], operation, content)) {
+          errorCount++;
+
+          if (errorCount > fuzzFactor) {
+            return false;
+          }
+        }
+
+        toPos++;
+      }
+    }
+
+    return true;
+  } // Search best fit offsets for each hunk based on the previous ones
+
+
+  for (var i = 0; i < hunks.length; i++) {
+    var hunk = hunks[i],
+        maxLine = lines.length - hunk.oldLines,
+        localOffset = 0,
+        toPos = offset + hunk.oldStart - 1;
+    var iterator = distanceIterator(toPos, minLine, maxLine);
+
+    for (; localOffset !== undefined; localOffset = iterator()) {
+      if (hunkFits(hunk, toPos + localOffset)) {
+        hunk.offset = offset += localOffset;
+        break;
+      }
+    }
+
+    if (localOffset === undefined) {
+      return false;
+    } // Set lower text limit to end of the current hunk, so next ones don't try
+    // to fit over already patched text
+
+
+    minLine = hunk.offset + hunk.oldStart + hunk.oldLines;
+  } // Apply patch hunks
+
+
+  var diffOffset = 0;
+
+  for (var _i = 0; _i < hunks.length; _i++) {
+    var _hunk = hunks[_i],
+        _toPos = _hunk.oldStart + _hunk.offset + diffOffset - 1;
+
+    diffOffset += _hunk.newLines - _hunk.oldLines;
+
+    if (_toPos < 0) {
+      // Creating a new file
+      _toPos = 0;
+    }
+
+    for (var j = 0; j < _hunk.lines.length; j++) {
+      var line = _hunk.lines[j],
+          operation = line.length > 0 ? line[0] : ' ',
+          content = line.length > 0 ? line.substr(1) : line,
+          delimiter = _hunk.linedelimiters[j];
+
+      if (operation === ' ') {
+        _toPos++;
+      } else if (operation === '-') {
+        lines.splice(_toPos, 1);
+        delimiters.splice(_toPos, 1);
+        /* istanbul ignore else */
+      } else if (operation === '+') {
+        lines.splice(_toPos, 0, content);
+        delimiters.splice(_toPos, 0, delimiter);
+        _toPos++;
+      } else if (operation === '\\') {
+        var previousOperation = _hunk.lines[j - 1] ? _hunk.lines[j - 1][0] : null;
+
+        if (previousOperation === '+') {
+          removeEOFNL = true;
+        } else if (previousOperation === '-') {
+          addEOFNL = true;
+        }
+      }
+    }
+  } // Handle EOFNL insertion/removal
+
+
+  if (removeEOFNL) {
+    while (!lines[lines.length - 1]) {
+      lines.pop();
+      delimiters.pop();
+    }
+  } else if (addEOFNL) {
+    lines.push('');
+    delimiters.push('\n');
+  }
+
+  for (var _k = 0; _k < lines.length - 1; _k++) {
+    lines[_k] = lines[_k] + delimiters[_k];
+  }
+
+  return lines.join('');
+} // Wrapper that supports multiple file patches via callbacks.
+
+function applyPatches(uniDiff, options) {
+  if (typeof uniDiff === 'string') {
+    uniDiff = parsePatch(uniDiff);
+  }
+
+  var currentIndex = 0;
+
+  function processIndex() {
+    var index = uniDiff[currentIndex++];
+
+    if (!index) {
+      return options.complete();
+    }
+
+    options.loadFile(index, function (err, data) {
+      if (err) {
+        return options.complete(err);
+      }
+
+      var updatedContent = applyPatch(data, index, options);
+      options.patched(index, updatedContent, function (err) {
+        if (err) {
+          return options.complete(err);
+        }
+
+        processIndex();
+      });
+    });
+  }
+
+  processIndex();
+}
+
+function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
+  if (!options) {
+    options = {};
+  }
+
+  if (typeof options.context === 'undefined') {
+    options.context = 4;
+  }
+
+  var diff = diffLines(oldStr, newStr, options);
+  diff.push({
+    value: '',
+    lines: []
+  }); // Append an empty value to make cleanup easier
+
+  function contextLines(lines) {
+    return lines.map(function (entry) {
+      return ' ' + entry;
+    });
+  }
+
+  var hunks = [];
+  var oldRangeStart = 0,
+      newRangeStart = 0,
+      curRange = [],
+      oldLine = 1,
+      newLine = 1;
+
+  var _loop = function _loop(i) {
+    var current = diff[i],
+        lines = current.lines || current.value.replace(/\n$/, '').split('\n');
+    current.lines = lines;
+
+    if (current.added || current.removed) {
+      var _curRange;
+
+      // If we have previous context, start with that
+      if (!oldRangeStart) {
+        var prev = diff[i - 1];
+        oldRangeStart = oldLine;
+        newRangeStart = newLine;
+
+        if (prev) {
+          curRange = options.context > 0 ? contextLines(prev.lines.slice(-options.context)) : [];
+          oldRangeStart -= curRange.length;
+          newRangeStart -= curRange.length;
+        }
+      } // Output our changes
+
+
+      (_curRange = curRange).push.apply(_curRange, _toConsumableArray(lines.map(function (entry) {
+        return (current.added ? '+' : '-') + entry;
+      }))); // Track the updated file position
+
+
+      if (current.added) {
+        newLine += lines.length;
+      } else {
+        oldLine += lines.length;
+      }
+    } else {
+      // Identical context lines. Track line changes
+      if (oldRangeStart) {
+        // Close out any changes that have been output (or join overlapping)
+        if (lines.length <= options.context * 2 && i < diff.length - 2) {
+          var _curRange2;
+
+          // Overlapping
+          (_curRange2 = curRange).push.apply(_curRange2, _toConsumableArray(contextLines(lines)));
+        } else {
+          var _curRange3;
+
+          // end the range and output
+          var contextSize = Math.min(lines.length, options.context);
+
+          (_curRange3 = curRange).push.apply(_curRange3, _toConsumableArray(contextLines(lines.slice(0, contextSize))));
+
+          var hunk = {
+            oldStart: oldRangeStart,
+            oldLines: oldLine - oldRangeStart + contextSize,
+            newStart: newRangeStart,
+            newLines: newLine - newRangeStart + contextSize,
+            lines: curRange
+          };
+
+          if (i >= diff.length - 2 && lines.length <= options.context) {
+            // EOF is inside this hunk
+            var oldEOFNewline = /\n$/.test(oldStr);
+            var newEOFNewline = /\n$/.test(newStr);
+            var noNlBeforeAdds = lines.length == 0 && curRange.length > hunk.oldLines;
+
+            if (!oldEOFNewline && noNlBeforeAdds) {
+              // special case: old has no eol and no trailing context; no-nl can end up before adds
+              curRange.splice(hunk.oldLines, 0, '\\ No newline at end of file');
+            }
+
+            if (!oldEOFNewline && !noNlBeforeAdds || !newEOFNewline) {
+              curRange.push('\\ No newline at end of file');
+            }
+          }
+
+          hunks.push(hunk);
+          oldRangeStart = 0;
+          newRangeStart = 0;
+          curRange = [];
+        }
+      }
+
+      oldLine += lines.length;
+      newLine += lines.length;
+    }
+  };
+
+  for (var i = 0; i < diff.length; i++) {
+    _loop(i);
+  }
+
+  return {
+    oldFileName: oldFileName,
+    newFileName: newFileName,
+    oldHeader: oldHeader,
+    newHeader: newHeader,
+    hunks: hunks
+  };
+}
+function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
+  var diff = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options);
+  var ret = [];
+
+  if (oldFileName == newFileName) {
+    ret.push('Index: ' + oldFileName);
+  }
+
+  ret.push('===================================================================');
+  ret.push('--- ' + diff.oldFileName + (typeof diff.oldHeader === 'undefined' ? '' : '\t' + diff.oldHeader));
+  ret.push('+++ ' + diff.newFileName + (typeof diff.newHeader === 'undefined' ? '' : '\t' + diff.newHeader));
+
+  for (var i = 0; i < diff.hunks.length; i++) {
+    var hunk = diff.hunks[i];
+    ret.push('@@ -' + hunk.oldStart + ',' + hunk.oldLines + ' +' + hunk.newStart + ',' + hunk.newLines + ' @@');
+    ret.push.apply(ret, hunk.lines);
+  }
+
+  return ret.join('\n') + '\n';
+}
+function createPatch(fileName, oldStr, newStr, oldHeader, newHeader, options) {
+  return createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader, options);
+}
+
+function arrayEqual(a, b) {
+  if (a.length !== b.length) {
+    return false;
+  }
+
+  return arrayStartsWith(a, b);
+}
+function arrayStartsWith(array, start) {
+  if (start.length > array.length) {
+    return false;
+  }
+
+  for (var i = 0; i < start.length; i++) {
+    if (start[i] !== array[i]) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+function calcLineCount(hunk) {
+  var _calcOldNewLineCount = calcOldNewLineCount(hunk.lines),
+      oldLines = _calcOldNewLineCount.oldLines,
+      newLines = _calcOldNewLineCount.newLines;
+
+  if (oldLines !== undefined) {
+    hunk.oldLines = oldLines;
+  } else {
+    delete hunk.oldLines;
+  }
+
+  if (newLines !== undefined) {
+    hunk.newLines = newLines;
+  } else {
+    delete hunk.newLines;
+  }
+}
+function merge(mine, theirs, base) {
+  mine = loadPatch(mine, base);
+  theirs = loadPatch(theirs, base);
+  var ret = {}; // For index we just let it pass through as it doesn't have any necessary meaning.
+  // Leaving sanity checks on this to the API consumer that may know more about the
+  // meaning in their own context.
+
+  if (mine.index || theirs.index) {
+    ret.index = mine.index || theirs.index;
+  }
+
+  if (mine.newFileName || theirs.newFileName) {
+    if (!fileNameChanged(mine)) {
+      // No header or no change in ours, use theirs (and ours if theirs does not exist)
+      ret.oldFileName = theirs.oldFileName || mine.oldFileName;
+      ret.newFileName = theirs.newFileName || mine.newFileName;
+      ret.oldHeader = theirs.oldHeader || mine.oldHeader;
+      ret.newHeader = theirs.newHeader || mine.newHeader;
+    } else if (!fileNameChanged(theirs)) {
+      // No header or no change in theirs, use ours
+      ret.oldFileName = mine.oldFileName;
+      ret.newFileName = mine.newFileName;
+      ret.oldHeader = mine.oldHeader;
+      ret.newHeader = mine.newHeader;
+    } else {
+      // Both changed... figure it out
+      ret.oldFileName = selectField(ret, mine.oldFileName, theirs.oldFileName);
+      ret.newFileName = selectField(ret, mine.newFileName, theirs.newFileName);
+      ret.oldHeader = selectField(ret, mine.oldHeader, theirs.oldHeader);
+      ret.newHeader = selectField(ret, mine.newHeader, theirs.newHeader);
+    }
+  }
+
+  ret.hunks = [];
+  var mineIndex = 0,
+      theirsIndex = 0,
+      mineOffset = 0,
+      theirsOffset = 0;
+
+  while (mineIndex < mine.hunks.length || theirsIndex < theirs.hunks.length) {
+    var mineCurrent = mine.hunks[mineIndex] || {
+      oldStart: Infinity
+    },
+        theirsCurrent = theirs.hunks[theirsIndex] || {
+      oldStart: Infinity
+    };
+
+    if (hunkBefore(mineCurrent, theirsCurrent)) {
+      // This patch does not overlap with any of the others, yay.
+      ret.hunks.push(cloneHunk(mineCurrent, mineOffset));
+      mineIndex++;
+      theirsOffset += mineCurrent.newLines - mineCurrent.oldLines;
+    } else if (hunkBefore(theirsCurrent, mineCurrent)) {
+      // This patch does not overlap with any of the others, yay.
+      ret.hunks.push(cloneHunk(theirsCurrent, theirsOffset));
+      theirsIndex++;
+      mineOffset += theirsCurrent.newLines - theirsCurrent.oldLines;
+    } else {
+      // Overlap, merge as best we can
+      var mergedHunk = {
+        oldStart: Math.min(mineCurrent.oldStart, theirsCurrent.oldStart),
+        oldLines: 0,
+        newStart: Math.min(mineCurrent.newStart + mineOffset, theirsCurrent.oldStart + theirsOffset),
+        newLines: 0,
+        lines: []
+      };
+      mergeLines(mergedHunk, mineCurrent.oldStart, mineCurrent.lines, theirsCurrent.oldStart, theirsCurrent.lines);
+      theirsIndex++;
+      mineIndex++;
+      ret.hunks.push(mergedHunk);
+    }
+  }
+
+  return ret;
+}
+
+function loadPatch(param, base) {
+  if (typeof param === 'string') {
+    if (/^@@/m.test(param) || /^Index:/m.test(param)) {
+      return parsePatch(param)[0];
+    }
+
+    if (!base) {
+      throw new Error('Must provide a base reference or pass in a patch');
+    }
+
+    return structuredPatch(undefined, undefined, base, param);
+  }
+
+  return param;
+}
+
+function fileNameChanged(patch) {
+  return patch.newFileName && patch.newFileName !== patch.oldFileName;
+}
+
+function selectField(index, mine, theirs) {
+  if (mine === theirs) {
+    return mine;
+  } else {
+    index.conflict = true;
+    return {
+      mine: mine,
+      theirs: theirs
+    };
+  }
+}
+
+function hunkBefore(test, check) {
+  return test.oldStart < check.oldStart && test.oldStart + test.oldLines < check.oldStart;
+}
+
+function cloneHunk(hunk, offset) {
+  return {
+    oldStart: hunk.oldStart,
+    oldLines: hunk.oldLines,
+    newStart: hunk.newStart + offset,
+    newLines: hunk.newLines,
+    lines: hunk.lines
+  };
+}
+
+function mergeLines(hunk, mineOffset, mineLines, theirOffset, theirLines) {
+  // This will generally result in a conflicted hunk, but there are cases where the context
+  // is the only overlap where we can successfully merge the content here.
+  var mine = {
+    offset: mineOffset,
+    lines: mineLines,
+    index: 0
+  },
+      their = {
+    offset: theirOffset,
+    lines: theirLines,
+    index: 0
+  }; // Handle any leading content
+
+  insertLeading(hunk, mine, their);
+  insertLeading(hunk, their, mine); // Now in the overlap content. Scan through and select the best changes from each.
+
+  while (mine.index < mine.lines.length && their.index < their.lines.length) {
+    var mineCurrent = mine.lines[mine.index],
+        theirCurrent = their.lines[their.index];
+
+    if ((mineCurrent[0] === '-' || mineCurrent[0] === '+') && (theirCurrent[0] === '-' || theirCurrent[0] === '+')) {
+      // Both modified ...
+      mutualChange(hunk, mine, their);
+    } else if (mineCurrent[0] === '+' && theirCurrent[0] === ' ') {
+      var _hunk$lines;
+
+      // Mine inserted
+      (_hunk$lines = hunk.lines).push.apply(_hunk$lines, _toConsumableArray(collectChange(mine)));
+    } else if (theirCurrent[0] === '+' && mineCurrent[0] === ' ') {
+      var _hunk$lines2;
+
+      // Theirs inserted
+      (_hunk$lines2 = hunk.lines).push.apply(_hunk$lines2, _toConsumableArray(collectChange(their)));
+    } else if (mineCurrent[0] === '-' && theirCurrent[0] === ' ') {
+      // Mine removed or edited
+      removal(hunk, mine, their);
+    } else if (theirCurrent[0] === '-' && mineCurrent[0] === ' ') {
+      // Their removed or edited
+      removal(hunk, their, mine, true);
+    } else if (mineCurrent === theirCurrent) {
+      // Context identity
+      hunk.lines.push(mineCurrent);
+      mine.index++;
+      their.index++;
+    } else {
+      // Context mismatch
+      conflict(hunk, collectChange(mine), collectChange(their));
+    }
+  } // Now push anything that may be remaining
+
+
+  insertTrailing(hunk, mine);
+  insertTrailing(hunk, their);
+  calcLineCount(hunk);
+}
+
+function mutualChange(hunk, mine, their) {
+  var myChanges = collectChange(mine),
+      theirChanges = collectChange(their);
+
+  if (allRemoves(myChanges) && allRemoves(theirChanges)) {
+    // Special case for remove changes that are supersets of one another
+    if (arrayStartsWith(myChanges, theirChanges) && skipRemoveSuperset(their, myChanges, myChanges.length - theirChanges.length)) {
+      var _hunk$lines3;
+
+      (_hunk$lines3 = hunk.lines).push.apply(_hunk$lines3, _toConsumableArray(myChanges));
+
+      return;
+    } else if (arrayStartsWith(theirChanges, myChanges) && skipRemoveSuperset(mine, theirChanges, theirChanges.length - myChanges.length)) {
+      var _hunk$lines4;
+
+      (_hunk$lines4 = hunk.lines).push.apply(_hunk$lines4, _toConsumableArray(theirChanges));
+
+      return;
+    }
+  } else if (arrayEqual(myChanges, theirChanges)) {
+    var _hunk$lines5;
+
+    (_hunk$lines5 = hunk.lines).push.apply(_hunk$lines5, _toConsumableArray(myChanges));
+
+    return;
+  }
+
+  conflict(hunk, myChanges, theirChanges);
+}
+
+function removal(hunk, mine, their, swap) {
+  var myChanges = collectChange(mine),
+      theirChanges = collectContext(their, myChanges);
+
+  if (theirChanges.merged) {
+    var _hunk$lines6;
+
+    (_hunk$lines6 = hunk.lines).push.apply(_hunk$lines6, _toConsumableArray(theirChanges.merged));
+  } else {
+    conflict(hunk, swap ? theirChanges : myChanges, swap ? myChanges : theirChanges);
+  }
+}
+
+function conflict(hunk, mine, their) {
+  hunk.conflict = true;
+  hunk.lines.push({
+    conflict: true,
+    mine: mine,
+    theirs: their
+  });
+}
+
+function insertLeading(hunk, insert, their) {
+  while (insert.offset < their.offset && insert.index < insert.lines.length) {
+    var line = insert.lines[insert.index++];
+    hunk.lines.push(line);
+    insert.offset++;
+  }
+}
+
+function insertTrailing(hunk, insert) {
+  while (insert.index < insert.lines.length) {
+    var line = insert.lines[insert.index++];
+    hunk.lines.push(line);
+  }
+}
+
+function collectChange(state) {
+  var ret = [],
+      operation = state.lines[state.index][0];
+
+  while (state.index < state.lines.length) {
+    var line = state.lines[state.index]; // Group additions that are immediately after subtractions and treat them as one "atomic" modify change.
+
+    if (operation === '-' && line[0] === '+') {
+      operation = '+';
+    }
+
+    if (operation === line[0]) {
+      ret.push(line);
+      state.index++;
+    } else {
+      break;
+    }
+  }
+
+  return ret;
+}
+
+function collectContext(state, matchChanges) {
+  var changes = [],
+      merged = [],
+      matchIndex = 0,
+      contextChanges = false,
+      conflicted = false;
+
+  while (matchIndex < matchChanges.length && state.index < state.lines.length) {
+    var change = state.lines[state.index],
+        match = matchChanges[matchIndex]; // Once we've hit our add, then we are done
+
+    if (match[0] === '+') {
+      break;
+    }
+
+    contextChanges = contextChanges || change[0] !== ' ';
+    merged.push(match);
+    matchIndex++; // Consume any additions in the other block as a conflict to attempt
+    // to pull in the remaining context after this
+
+    if (change[0] === '+') {
+      conflicted = true;
+
+      while (change[0] === '+') {
+        changes.push(change);
+        change = state.lines[++state.index];
+      }
+    }
+
+    if (match.substr(1) === change.substr(1)) {
+      changes.push(change);
+      state.index++;
+    } else {
+      conflicted = true;
+    }
+  }
+
+  if ((matchChanges[matchIndex] || '')[0] === '+' && contextChanges) {
+    conflicted = true;
+  }
+
+  if (conflicted) {
+    return changes;
+  }
+
+  while (matchIndex < matchChanges.length) {
+    merged.push(matchChanges[matchIndex++]);
+  }
+
+  return {
+    merged: merged,
+    changes: changes
+  };
+}
+
+function allRemoves(changes) {
+  return changes.reduce(function (prev, change) {
+    return prev && change[0] === '-';
+  }, true);
+}
+
+function skipRemoveSuperset(state, removeChanges, delta) {
+  for (var i = 0; i < delta; i++) {
+    var changeContent = removeChanges[removeChanges.length - delta + i].substr(1);
+
+    if (state.lines[state.index + i] !== ' ' + changeContent) {
+      return false;
+    }
+  }
+
+  state.index += delta;
+  return true;
+}
+
+function calcOldNewLineCount(lines) {
+  var oldLines = 0;
+  var newLines = 0;
+  lines.forEach(function (line) {
+    if (typeof line !== 'string') {
+      var myCount = calcOldNewLineCount(line.mine);
+      var theirCount = calcOldNewLineCount(line.theirs);
+
+      if (oldLines !== undefined) {
+        if (myCount.oldLines === theirCount.oldLines) {
+          oldLines += myCount.oldLines;
+        } else {
+          oldLines = undefined;
+        }
+      }
+
+      if (newLines !== undefined) {
+        if (myCount.newLines === theirCount.newLines) {
+          newLines += myCount.newLines;
+        } else {
+          newLines = undefined;
+        }
+      }
+    } else {
+      if (newLines !== undefined && (line[0] === '+' || line[0] === ' ')) {
+        newLines++;
+      }
+
+      if (oldLines !== undefined && (line[0] === '-' || line[0] === ' ')) {
+        oldLines++;
+      }
+    }
+  });
+  return {
+    oldLines: oldLines,
+    newLines: newLines
+  };
+}
+
+// See: http://code.google.com/p/google-diff-match-patch/wiki/API
+function convertChangesToDMP(changes) {
+  var ret = [],
+      change,
+      operation;
+
+  for (var i = 0; i < changes.length; i++) {
+    change = changes[i];
+
+    if (change.added) {
+      operation = 1;
+    } else if (change.removed) {
+      operation = -1;
+    } else {
+      operation = 0;
+    }
+
+    ret.push([operation, change.value]);
+  }
+
+  return ret;
+}
+
+function convertChangesToXML(changes) {
+  var ret = [];
+
+  for (var i = 0; i < changes.length; i++) {
+    var change = changes[i];
+
+    if (change.added) {
+      ret.push('');
+    } else if (change.removed) {
+      ret.push('');
+    }
+
+    ret.push(escapeHTML(change.value));
+
+    if (change.added) {
+      ret.push('');
+    } else if (change.removed) {
+      ret.push('');
+    }
+  }
+
+  return ret.join('');
+}
+
+function escapeHTML(s) {
+  var n = s;
+  n = n.replace(/&/g, '&');
+  n = n.replace(//g, '>');
+  n = n.replace(/"/g, '"');
+  return n;
+}
+
+/* See LICENSE file for terms of use */
+
+export { Diff, diffChars, diffWords, diffWordsWithSpace, diffLines, diffTrimmedLines, diffSentences, diffCss, diffJson, diffArrays, structuredPatch, createTwoFilesPatch, createPatch, applyPatch, applyPatches, parsePatch, merge, convertChangesToDMP, convertChangesToXML, canonicalize };
diff --git a/node_modules/libtap/node_modules/diff/lib/index.js b/node_modules/libtap/node_modules/diff/lib/index.js
new file mode 100644
index 0000000000000..ff8ae919095c2
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/index.js
@@ -0,0 +1,216 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+Object.defineProperty(exports, "Diff", {
+  enumerable: true,
+  get: function get() {
+    return _base.default;
+  }
+});
+Object.defineProperty(exports, "diffChars", {
+  enumerable: true,
+  get: function get() {
+    return _character.diffChars;
+  }
+});
+Object.defineProperty(exports, "diffWords", {
+  enumerable: true,
+  get: function get() {
+    return _word.diffWords;
+  }
+});
+Object.defineProperty(exports, "diffWordsWithSpace", {
+  enumerable: true,
+  get: function get() {
+    return _word.diffWordsWithSpace;
+  }
+});
+Object.defineProperty(exports, "diffLines", {
+  enumerable: true,
+  get: function get() {
+    return _line.diffLines;
+  }
+});
+Object.defineProperty(exports, "diffTrimmedLines", {
+  enumerable: true,
+  get: function get() {
+    return _line.diffTrimmedLines;
+  }
+});
+Object.defineProperty(exports, "diffSentences", {
+  enumerable: true,
+  get: function get() {
+    return _sentence.diffSentences;
+  }
+});
+Object.defineProperty(exports, "diffCss", {
+  enumerable: true,
+  get: function get() {
+    return _css.diffCss;
+  }
+});
+Object.defineProperty(exports, "diffJson", {
+  enumerable: true,
+  get: function get() {
+    return _json.diffJson;
+  }
+});
+Object.defineProperty(exports, "canonicalize", {
+  enumerable: true,
+  get: function get() {
+    return _json.canonicalize;
+  }
+});
+Object.defineProperty(exports, "diffArrays", {
+  enumerable: true,
+  get: function get() {
+    return _array.diffArrays;
+  }
+});
+Object.defineProperty(exports, "applyPatch", {
+  enumerable: true,
+  get: function get() {
+    return _apply.applyPatch;
+  }
+});
+Object.defineProperty(exports, "applyPatches", {
+  enumerable: true,
+  get: function get() {
+    return _apply.applyPatches;
+  }
+});
+Object.defineProperty(exports, "parsePatch", {
+  enumerable: true,
+  get: function get() {
+    return _parse.parsePatch;
+  }
+});
+Object.defineProperty(exports, "merge", {
+  enumerable: true,
+  get: function get() {
+    return _merge.merge;
+  }
+});
+Object.defineProperty(exports, "structuredPatch", {
+  enumerable: true,
+  get: function get() {
+    return _create.structuredPatch;
+  }
+});
+Object.defineProperty(exports, "createTwoFilesPatch", {
+  enumerable: true,
+  get: function get() {
+    return _create.createTwoFilesPatch;
+  }
+});
+Object.defineProperty(exports, "createPatch", {
+  enumerable: true,
+  get: function get() {
+    return _create.createPatch;
+  }
+});
+Object.defineProperty(exports, "convertChangesToDMP", {
+  enumerable: true,
+  get: function get() {
+    return _dmp.convertChangesToDMP;
+  }
+});
+Object.defineProperty(exports, "convertChangesToXML", {
+  enumerable: true,
+  get: function get() {
+    return _xml.convertChangesToXML;
+  }
+});
+
+/*istanbul ignore end*/
+var
+/*istanbul ignore start*/
+_base = _interopRequireDefault(require("./diff/base"))
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_character = require("./diff/character")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_word = require("./diff/word")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_line = require("./diff/line")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_sentence = require("./diff/sentence")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_css = require("./diff/css")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_json = require("./diff/json")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_array = require("./diff/array")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_apply = require("./patch/apply")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_parse = require("./patch/parse")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_merge = require("./patch/merge")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_create = require("./patch/create")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_dmp = require("./convert/dmp")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_xml = require("./convert/xml")
+/*istanbul ignore end*/
+;
+
+/*istanbul ignore start*/ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/*istanbul ignore end*/
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWdCQTtBQUFBO0FBQUE7QUFBQTtBQUFBOztBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7O0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTs7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBOztBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7O0FBRUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBOztBQUVBO0FBQUE7QUFBQTtBQUFBO0FBQUE7O0FBRUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBOztBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7O0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTs7QUFFQTtBQUFBO0FBQUE7QUFBQTtBQUFBOztBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUEiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBTZWUgTElDRU5TRSBmaWxlIGZvciB0ZXJtcyBvZiB1c2UgKi9cblxuLypcbiAqIFRleHQgZGlmZiBpbXBsZW1lbnRhdGlvbi5cbiAqXG4gKiBUaGlzIGxpYnJhcnkgc3VwcG9ydHMgdGhlIGZvbGxvd2luZyBBUElTOlxuICogSnNEaWZmLmRpZmZDaGFyczogQ2hhcmFjdGVyIGJ5IGNoYXJhY3RlciBkaWZmXG4gKiBKc0RpZmYuZGlmZldvcmRzOiBXb3JkIChhcyBkZWZpbmVkIGJ5IFxcYiByZWdleCkgZGlmZiB3aGljaCBpZ25vcmVzIHdoaXRlc3BhY2VcbiAqIEpzRGlmZi5kaWZmTGluZXM6IExpbmUgYmFzZWQgZGlmZlxuICpcbiAqIEpzRGlmZi5kaWZmQ3NzOiBEaWZmIHRhcmdldGVkIGF0IENTUyBjb250ZW50XG4gKlxuICogVGhlc2UgbWV0aG9kcyBhcmUgYmFzZWQgb24gdGhlIGltcGxlbWVudGF0aW9uIHByb3Bvc2VkIGluXG4gKiBcIkFuIE8oTkQpIERpZmZlcmVuY2UgQWxnb3JpdGhtIGFuZCBpdHMgVmFyaWF0aW9uc1wiIChNeWVycywgMTk4NikuXG4gKiBodHRwOi8vY2l0ZXNlZXJ4LmlzdC5wc3UuZWR1L3ZpZXdkb2Mvc3VtbWFyeT9kb2k9MTAuMS4xLjQuNjkyN1xuICovXG5pbXBvcnQgRGlmZiBmcm9tICcuL2RpZmYvYmFzZSc7XG5pbXBvcnQge2RpZmZDaGFyc30gZnJvbSAnLi9kaWZmL2NoYXJhY3Rlcic7XG5pbXBvcnQge2RpZmZXb3JkcywgZGlmZldvcmRzV2l0aFNwYWNlfSBmcm9tICcuL2RpZmYvd29yZCc7XG5pbXBvcnQge2RpZmZMaW5lcywgZGlmZlRyaW1tZWRMaW5lc30gZnJvbSAnLi9kaWZmL2xpbmUnO1xuaW1wb3J0IHtkaWZmU2VudGVuY2VzfSBmcm9tICcuL2RpZmYvc2VudGVuY2UnO1xuXG5pbXBvcnQge2RpZmZDc3N9IGZyb20gJy4vZGlmZi9jc3MnO1xuaW1wb3J0IHtkaWZmSnNvbiwgY2Fub25pY2FsaXplfSBmcm9tICcuL2RpZmYvanNvbic7XG5cbmltcG9ydCB7ZGlmZkFycmF5c30gZnJvbSAnLi9kaWZmL2FycmF5JztcblxuaW1wb3J0IHthcHBseVBhdGNoLCBhcHBseVBhdGNoZXN9IGZyb20gJy4vcGF0Y2gvYXBwbHknO1xuaW1wb3J0IHtwYXJzZVBhdGNofSBmcm9tICcuL3BhdGNoL3BhcnNlJztcbmltcG9ydCB7bWVyZ2V9IGZyb20gJy4vcGF0Y2gvbWVyZ2UnO1xuaW1wb3J0IHtzdHJ1Y3R1cmVkUGF0Y2gsIGNyZWF0ZVR3b0ZpbGVzUGF0Y2gsIGNyZWF0ZVBhdGNofSBmcm9tICcuL3BhdGNoL2NyZWF0ZSc7XG5cbmltcG9ydCB7Y29udmVydENoYW5nZXNUb0RNUH0gZnJvbSAnLi9jb252ZXJ0L2RtcCc7XG5pbXBvcnQge2NvbnZlcnRDaGFuZ2VzVG9YTUx9IGZyb20gJy4vY29udmVydC94bWwnO1xuXG5leHBvcnQge1xuICBEaWZmLFxuXG4gIGRpZmZDaGFycyxcbiAgZGlmZldvcmRzLFxuICBkaWZmV29yZHNXaXRoU3BhY2UsXG4gIGRpZmZMaW5lcyxcbiAgZGlmZlRyaW1tZWRMaW5lcyxcbiAgZGlmZlNlbnRlbmNlcyxcblxuICBkaWZmQ3NzLFxuICBkaWZmSnNvbixcblxuICBkaWZmQXJyYXlzLFxuXG4gIHN0cnVjdHVyZWRQYXRjaCxcbiAgY3JlYXRlVHdvRmlsZXNQYXRjaCxcbiAgY3JlYXRlUGF0Y2gsXG4gIGFwcGx5UGF0Y2gsXG4gIGFwcGx5UGF0Y2hlcyxcbiAgcGFyc2VQYXRjaCxcbiAgbWVyZ2UsXG4gIGNvbnZlcnRDaGFuZ2VzVG9ETVAsXG4gIGNvbnZlcnRDaGFuZ2VzVG9YTUwsXG4gIGNhbm9uaWNhbGl6ZVxufTtcbiJdfQ==
diff --git a/node_modules/libtap/node_modules/diff/lib/patch/apply.js b/node_modules/libtap/node_modules/diff/lib/patch/apply.js
new file mode 100644
index 0000000000000..19bddd8970e51
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/patch/apply.js
@@ -0,0 +1,243 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.applyPatch = applyPatch;
+exports.applyPatches = applyPatches;
+
+/*istanbul ignore end*/
+var
+/*istanbul ignore start*/
+_parse = require("./parse")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_distanceIterator = _interopRequireDefault(require("../util/distance-iterator"))
+/*istanbul ignore end*/
+;
+
+/*istanbul ignore start*/ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/*istanbul ignore end*/
+function applyPatch(source, uniDiff) {
+  /*istanbul ignore start*/
+  var
+  /*istanbul ignore end*/
+  options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
+
+  if (typeof uniDiff === 'string') {
+    uniDiff =
+    /*istanbul ignore start*/
+    (0,
+    /*istanbul ignore end*/
+
+    /*istanbul ignore start*/
+    _parse
+    /*istanbul ignore end*/
+    .
+    /*istanbul ignore start*/
+    parsePatch)
+    /*istanbul ignore end*/
+    (uniDiff);
+  }
+
+  if (Array.isArray(uniDiff)) {
+    if (uniDiff.length > 1) {
+      throw new Error('applyPatch only works with a single input.');
+    }
+
+    uniDiff = uniDiff[0];
+  } // Apply the diff to the input
+
+
+  var lines = source.split(/\r\n|[\n\v\f\r\x85]/),
+      delimiters = source.match(/\r\n|[\n\v\f\r\x85]/g) || [],
+      hunks = uniDiff.hunks,
+      compareLine = options.compareLine || function (lineNumber, line, operation, patchContent)
+  /*istanbul ignore start*/
+  {
+    return (
+      /*istanbul ignore end*/
+      line === patchContent
+    );
+  },
+      errorCount = 0,
+      fuzzFactor = options.fuzzFactor || 0,
+      minLine = 0,
+      offset = 0,
+      removeEOFNL,
+      addEOFNL;
+  /**
+   * Checks if the hunk exactly fits on the provided location
+   */
+
+
+  function hunkFits(hunk, toPos) {
+    for (var j = 0; j < hunk.lines.length; j++) {
+      var line = hunk.lines[j],
+          operation = line.length > 0 ? line[0] : ' ',
+          content = line.length > 0 ? line.substr(1) : line;
+
+      if (operation === ' ' || operation === '-') {
+        // Context sanity check
+        if (!compareLine(toPos + 1, lines[toPos], operation, content)) {
+          errorCount++;
+
+          if (errorCount > fuzzFactor) {
+            return false;
+          }
+        }
+
+        toPos++;
+      }
+    }
+
+    return true;
+  } // Search best fit offsets for each hunk based on the previous ones
+
+
+  for (var i = 0; i < hunks.length; i++) {
+    var hunk = hunks[i],
+        maxLine = lines.length - hunk.oldLines,
+        localOffset = 0,
+        toPos = offset + hunk.oldStart - 1;
+    var iterator =
+    /*istanbul ignore start*/
+    (0,
+    /*istanbul ignore end*/
+
+    /*istanbul ignore start*/
+    _distanceIterator
+    /*istanbul ignore end*/
+    .
+    /*istanbul ignore start*/
+    default)
+    /*istanbul ignore end*/
+    (toPos, minLine, maxLine);
+
+    for (; localOffset !== undefined; localOffset = iterator()) {
+      if (hunkFits(hunk, toPos + localOffset)) {
+        hunk.offset = offset += localOffset;
+        break;
+      }
+    }
+
+    if (localOffset === undefined) {
+      return false;
+    } // Set lower text limit to end of the current hunk, so next ones don't try
+    // to fit over already patched text
+
+
+    minLine = hunk.offset + hunk.oldStart + hunk.oldLines;
+  } // Apply patch hunks
+
+
+  var diffOffset = 0;
+
+  for (var _i = 0; _i < hunks.length; _i++) {
+    var _hunk = hunks[_i],
+        _toPos = _hunk.oldStart + _hunk.offset + diffOffset - 1;
+
+    diffOffset += _hunk.newLines - _hunk.oldLines;
+
+    if (_toPos < 0) {
+      // Creating a new file
+      _toPos = 0;
+    }
+
+    for (var j = 0; j < _hunk.lines.length; j++) {
+      var line = _hunk.lines[j],
+          operation = line.length > 0 ? line[0] : ' ',
+          content = line.length > 0 ? line.substr(1) : line,
+          delimiter = _hunk.linedelimiters[j];
+
+      if (operation === ' ') {
+        _toPos++;
+      } else if (operation === '-') {
+        lines.splice(_toPos, 1);
+        delimiters.splice(_toPos, 1);
+        /* istanbul ignore else */
+      } else if (operation === '+') {
+        lines.splice(_toPos, 0, content);
+        delimiters.splice(_toPos, 0, delimiter);
+        _toPos++;
+      } else if (operation === '\\') {
+        var previousOperation = _hunk.lines[j - 1] ? _hunk.lines[j - 1][0] : null;
+
+        if (previousOperation === '+') {
+          removeEOFNL = true;
+        } else if (previousOperation === '-') {
+          addEOFNL = true;
+        }
+      }
+    }
+  } // Handle EOFNL insertion/removal
+
+
+  if (removeEOFNL) {
+    while (!lines[lines.length - 1]) {
+      lines.pop();
+      delimiters.pop();
+    }
+  } else if (addEOFNL) {
+    lines.push('');
+    delimiters.push('\n');
+  }
+
+  for (var _k = 0; _k < lines.length - 1; _k++) {
+    lines[_k] = lines[_k] + delimiters[_k];
+  }
+
+  return lines.join('');
+} // Wrapper that supports multiple file patches via callbacks.
+
+
+function applyPatches(uniDiff, options) {
+  if (typeof uniDiff === 'string') {
+    uniDiff =
+    /*istanbul ignore start*/
+    (0,
+    /*istanbul ignore end*/
+
+    /*istanbul ignore start*/
+    _parse
+    /*istanbul ignore end*/
+    .
+    /*istanbul ignore start*/
+    parsePatch)
+    /*istanbul ignore end*/
+    (uniDiff);
+  }
+
+  var currentIndex = 0;
+
+  function processIndex() {
+    var index = uniDiff[currentIndex++];
+
+    if (!index) {
+      return options.complete();
+    }
+
+    options.loadFile(index, function (err, data) {
+      if (err) {
+        return options.complete(err);
+      }
+
+      var updatedContent = applyPatch(data, index, options);
+      options.patched(index, updatedContent, function (err) {
+        if (err) {
+          return options.complete(err);
+        }
+
+        processIndex();
+      });
+    });
+  }
+
+  processIndex();
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYXRjaC9hcHBseS5qcyJdLCJuYW1lcyI6WyJhcHBseVBhdGNoIiwic291cmNlIiwidW5pRGlmZiIsIm9wdGlvbnMiLCJwYXJzZVBhdGNoIiwiQXJyYXkiLCJpc0FycmF5IiwibGVuZ3RoIiwiRXJyb3IiLCJsaW5lcyIsInNwbGl0IiwiZGVsaW1pdGVycyIsIm1hdGNoIiwiaHVua3MiLCJjb21wYXJlTGluZSIsImxpbmVOdW1iZXIiLCJsaW5lIiwib3BlcmF0aW9uIiwicGF0Y2hDb250ZW50IiwiZXJyb3JDb3VudCIsImZ1enpGYWN0b3IiLCJtaW5MaW5lIiwib2Zmc2V0IiwicmVtb3ZlRU9GTkwiLCJhZGRFT0ZOTCIsImh1bmtGaXRzIiwiaHVuayIsInRvUG9zIiwiaiIsImNvbnRlbnQiLCJzdWJzdHIiLCJpIiwibWF4TGluZSIsIm9sZExpbmVzIiwibG9jYWxPZmZzZXQiLCJvbGRTdGFydCIsIml0ZXJhdG9yIiwiZGlzdGFuY2VJdGVyYXRvciIsInVuZGVmaW5lZCIsImRpZmZPZmZzZXQiLCJuZXdMaW5lcyIsImRlbGltaXRlciIsImxpbmVkZWxpbWl0ZXJzIiwic3BsaWNlIiwicHJldmlvdXNPcGVyYXRpb24iLCJwb3AiLCJwdXNoIiwiX2siLCJqb2luIiwiYXBwbHlQYXRjaGVzIiwiY3VycmVudEluZGV4IiwicHJvY2Vzc0luZGV4IiwiaW5kZXgiLCJjb21wbGV0ZSIsImxvYWRGaWxlIiwiZXJyIiwiZGF0YSIsInVwZGF0ZWRDb250ZW50IiwicGF0Y2hlZCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7O0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTs7Ozs7QUFFTyxTQUFTQSxVQUFULENBQW9CQyxNQUFwQixFQUE0QkMsT0FBNUIsRUFBbUQ7QUFBQTtBQUFBO0FBQUE7QUFBZEMsRUFBQUEsT0FBYyx1RUFBSixFQUFJOztBQUN4RCxNQUFJLE9BQU9ELE9BQVAsS0FBbUIsUUFBdkIsRUFBaUM7QUFDL0JBLElBQUFBLE9BQU87QUFBRztBQUFBO0FBQUE7O0FBQUFFO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUE7QUFBQSxLQUFXRixPQUFYLENBQVY7QUFDRDs7QUFFRCxNQUFJRyxLQUFLLENBQUNDLE9BQU4sQ0FBY0osT0FBZCxDQUFKLEVBQTRCO0FBQzFCLFFBQUlBLE9BQU8sQ0FBQ0ssTUFBUixHQUFpQixDQUFyQixFQUF3QjtBQUN0QixZQUFNLElBQUlDLEtBQUosQ0FBVSw0Q0FBVixDQUFOO0FBQ0Q7O0FBRUROLElBQUFBLE9BQU8sR0FBR0EsT0FBTyxDQUFDLENBQUQsQ0FBakI7QUFDRCxHQVh1RCxDQWF4RDs7O0FBQ0EsTUFBSU8sS0FBSyxHQUFHUixNQUFNLENBQUNTLEtBQVAsQ0FBYSxxQkFBYixDQUFaO0FBQUEsTUFDSUMsVUFBVSxHQUFHVixNQUFNLENBQUNXLEtBQVAsQ0FBYSxzQkFBYixLQUF3QyxFQUR6RDtBQUFBLE1BRUlDLEtBQUssR0FBR1gsT0FBTyxDQUFDVyxLQUZwQjtBQUFBLE1BSUlDLFdBQVcsR0FBR1gsT0FBTyxDQUFDVyxXQUFSLElBQXdCLFVBQUNDLFVBQUQsRUFBYUMsSUFBYixFQUFtQkMsU0FBbkIsRUFBOEJDLFlBQTlCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBK0NGLE1BQUFBLElBQUksS0FBS0U7QUFBeEQ7QUFBQSxHQUoxQztBQUFBLE1BS0lDLFVBQVUsR0FBRyxDQUxqQjtBQUFBLE1BTUlDLFVBQVUsR0FBR2pCLE9BQU8sQ0FBQ2lCLFVBQVIsSUFBc0IsQ0FOdkM7QUFBQSxNQU9JQyxPQUFPLEdBQUcsQ0FQZDtBQUFBLE1BUUlDLE1BQU0sR0FBRyxDQVJiO0FBQUEsTUFVSUMsV0FWSjtBQUFBLE1BV0lDLFFBWEo7QUFhQTs7Ozs7QUFHQSxXQUFTQyxRQUFULENBQWtCQyxJQUFsQixFQUF3QkMsS0FBeEIsRUFBK0I7QUFDN0IsU0FBSyxJQUFJQyxDQUFDLEdBQUcsQ0FBYixFQUFnQkEsQ0FBQyxHQUFHRixJQUFJLENBQUNqQixLQUFMLENBQVdGLE1BQS9CLEVBQXVDcUIsQ0FBQyxFQUF4QyxFQUE0QztBQUMxQyxVQUFJWixJQUFJLEdBQUdVLElBQUksQ0FBQ2pCLEtBQUwsQ0FBV21CLENBQVgsQ0FBWDtBQUFBLFVBQ0lYLFNBQVMsR0FBSUQsSUFBSSxDQUFDVCxNQUFMLEdBQWMsQ0FBZCxHQUFrQlMsSUFBSSxDQUFDLENBQUQsQ0FBdEIsR0FBNEIsR0FEN0M7QUFBQSxVQUVJYSxPQUFPLEdBQUliLElBQUksQ0FBQ1QsTUFBTCxHQUFjLENBQWQsR0FBa0JTLElBQUksQ0FBQ2MsTUFBTCxDQUFZLENBQVosQ0FBbEIsR0FBbUNkLElBRmxEOztBQUlBLFVBQUlDLFNBQVMsS0FBSyxHQUFkLElBQXFCQSxTQUFTLEtBQUssR0FBdkMsRUFBNEM7QUFDMUM7QUFDQSxZQUFJLENBQUNILFdBQVcsQ0FBQ2EsS0FBSyxHQUFHLENBQVQsRUFBWWxCLEtBQUssQ0FBQ2tCLEtBQUQsQ0FBakIsRUFBMEJWLFNBQTFCLEVBQXFDWSxPQUFyQyxDQUFoQixFQUErRDtBQUM3RFYsVUFBQUEsVUFBVTs7QUFFVixjQUFJQSxVQUFVLEdBQUdDLFVBQWpCLEVBQTZCO0FBQzNCLG1CQUFPLEtBQVA7QUFDRDtBQUNGOztBQUNETyxRQUFBQSxLQUFLO0FBQ047QUFDRjs7QUFFRCxXQUFPLElBQVA7QUFDRCxHQWxEdUQsQ0FvRHhEOzs7QUFDQSxPQUFLLElBQUlJLENBQUMsR0FBRyxDQUFiLEVBQWdCQSxDQUFDLEdBQUdsQixLQUFLLENBQUNOLE1BQTFCLEVBQWtDd0IsQ0FBQyxFQUFuQyxFQUF1QztBQUNyQyxRQUFJTCxJQUFJLEdBQUdiLEtBQUssQ0FBQ2tCLENBQUQsQ0FBaEI7QUFBQSxRQUNJQyxPQUFPLEdBQUd2QixLQUFLLENBQUNGLE1BQU4sR0FBZW1CLElBQUksQ0FBQ08sUUFEbEM7QUFBQSxRQUVJQyxXQUFXLEdBQUcsQ0FGbEI7QUFBQSxRQUdJUCxLQUFLLEdBQUdMLE1BQU0sR0FBR0ksSUFBSSxDQUFDUyxRQUFkLEdBQXlCLENBSHJDO0FBS0EsUUFBSUMsUUFBUTtBQUFHO0FBQUE7QUFBQTs7QUFBQUM7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQTtBQUFBLEtBQWlCVixLQUFqQixFQUF3Qk4sT0FBeEIsRUFBaUNXLE9BQWpDLENBQWY7O0FBRUEsV0FBT0UsV0FBVyxLQUFLSSxTQUF2QixFQUFrQ0osV0FBVyxHQUFHRSxRQUFRLEVBQXhELEVBQTREO0FBQzFELFVBQUlYLFFBQVEsQ0FBQ0MsSUFBRCxFQUFPQyxLQUFLLEdBQUdPLFdBQWYsQ0FBWixFQUF5QztBQUN2Q1IsUUFBQUEsSUFBSSxDQUFDSixNQUFMLEdBQWNBLE1BQU0sSUFBSVksV0FBeEI7QUFDQTtBQUNEO0FBQ0Y7O0FBRUQsUUFBSUEsV0FBVyxLQUFLSSxTQUFwQixFQUErQjtBQUM3QixhQUFPLEtBQVA7QUFDRCxLQWpCb0MsQ0FtQnJDO0FBQ0E7OztBQUNBakIsSUFBQUEsT0FBTyxHQUFHSyxJQUFJLENBQUNKLE1BQUwsR0FBY0ksSUFBSSxDQUFDUyxRQUFuQixHQUE4QlQsSUFBSSxDQUFDTyxRQUE3QztBQUNELEdBM0V1RCxDQTZFeEQ7OztBQUNBLE1BQUlNLFVBQVUsR0FBRyxDQUFqQjs7QUFDQSxPQUFLLElBQUlSLEVBQUMsR0FBRyxDQUFiLEVBQWdCQSxFQUFDLEdBQUdsQixLQUFLLENBQUNOLE1BQTFCLEVBQWtDd0IsRUFBQyxFQUFuQyxFQUF1QztBQUNyQyxRQUFJTCxLQUFJLEdBQUdiLEtBQUssQ0FBQ2tCLEVBQUQsQ0FBaEI7QUFBQSxRQUNJSixNQUFLLEdBQUdELEtBQUksQ0FBQ1MsUUFBTCxHQUFnQlQsS0FBSSxDQUFDSixNQUFyQixHQUE4QmlCLFVBQTlCLEdBQTJDLENBRHZEOztBQUVBQSxJQUFBQSxVQUFVLElBQUliLEtBQUksQ0FBQ2MsUUFBTCxHQUFnQmQsS0FBSSxDQUFDTyxRQUFuQzs7QUFFQSxRQUFJTixNQUFLLEdBQUcsQ0FBWixFQUFlO0FBQUU7QUFDZkEsTUFBQUEsTUFBSyxHQUFHLENBQVI7QUFDRDs7QUFFRCxTQUFLLElBQUlDLENBQUMsR0FBRyxDQUFiLEVBQWdCQSxDQUFDLEdBQUdGLEtBQUksQ0FBQ2pCLEtBQUwsQ0FBV0YsTUFBL0IsRUFBdUNxQixDQUFDLEVBQXhDLEVBQTRDO0FBQzFDLFVBQUlaLElBQUksR0FBR1UsS0FBSSxDQUFDakIsS0FBTCxDQUFXbUIsQ0FBWCxDQUFYO0FBQUEsVUFDSVgsU0FBUyxHQUFJRCxJQUFJLENBQUNULE1BQUwsR0FBYyxDQUFkLEdBQWtCUyxJQUFJLENBQUMsQ0FBRCxDQUF0QixHQUE0QixHQUQ3QztBQUFBLFVBRUlhLE9BQU8sR0FBSWIsSUFBSSxDQUFDVCxNQUFMLEdBQWMsQ0FBZCxHQUFrQlMsSUFBSSxDQUFDYyxNQUFMLENBQVksQ0FBWixDQUFsQixHQUFtQ2QsSUFGbEQ7QUFBQSxVQUdJeUIsU0FBUyxHQUFHZixLQUFJLENBQUNnQixjQUFMLENBQW9CZCxDQUFwQixDQUhoQjs7QUFLQSxVQUFJWCxTQUFTLEtBQUssR0FBbEIsRUFBdUI7QUFDckJVLFFBQUFBLE1BQUs7QUFDTixPQUZELE1BRU8sSUFBSVYsU0FBUyxLQUFLLEdBQWxCLEVBQXVCO0FBQzVCUixRQUFBQSxLQUFLLENBQUNrQyxNQUFOLENBQWFoQixNQUFiLEVBQW9CLENBQXBCO0FBQ0FoQixRQUFBQSxVQUFVLENBQUNnQyxNQUFYLENBQWtCaEIsTUFBbEIsRUFBeUIsQ0FBekI7QUFDRjtBQUNDLE9BSk0sTUFJQSxJQUFJVixTQUFTLEtBQUssR0FBbEIsRUFBdUI7QUFDNUJSLFFBQUFBLEtBQUssQ0FBQ2tDLE1BQU4sQ0FBYWhCLE1BQWIsRUFBb0IsQ0FBcEIsRUFBdUJFLE9BQXZCO0FBQ0FsQixRQUFBQSxVQUFVLENBQUNnQyxNQUFYLENBQWtCaEIsTUFBbEIsRUFBeUIsQ0FBekIsRUFBNEJjLFNBQTVCO0FBQ0FkLFFBQUFBLE1BQUs7QUFDTixPQUpNLE1BSUEsSUFBSVYsU0FBUyxLQUFLLElBQWxCLEVBQXdCO0FBQzdCLFlBQUkyQixpQkFBaUIsR0FBR2xCLEtBQUksQ0FBQ2pCLEtBQUwsQ0FBV21CLENBQUMsR0FBRyxDQUFmLElBQW9CRixLQUFJLENBQUNqQixLQUFMLENBQVdtQixDQUFDLEdBQUcsQ0FBZixFQUFrQixDQUFsQixDQUFwQixHQUEyQyxJQUFuRTs7QUFDQSxZQUFJZ0IsaUJBQWlCLEtBQUssR0FBMUIsRUFBK0I7QUFDN0JyQixVQUFBQSxXQUFXLEdBQUcsSUFBZDtBQUNELFNBRkQsTUFFTyxJQUFJcUIsaUJBQWlCLEtBQUssR0FBMUIsRUFBK0I7QUFDcENwQixVQUFBQSxRQUFRLEdBQUcsSUFBWDtBQUNEO0FBQ0Y7QUFDRjtBQUNGLEdBakh1RCxDQW1IeEQ7OztBQUNBLE1BQUlELFdBQUosRUFBaUI7QUFDZixXQUFPLENBQUNkLEtBQUssQ0FBQ0EsS0FBSyxDQUFDRixNQUFOLEdBQWUsQ0FBaEIsQ0FBYixFQUFpQztBQUMvQkUsTUFBQUEsS0FBSyxDQUFDb0MsR0FBTjtBQUNBbEMsTUFBQUEsVUFBVSxDQUFDa0MsR0FBWDtBQUNEO0FBQ0YsR0FMRCxNQUtPLElBQUlyQixRQUFKLEVBQWM7QUFDbkJmLElBQUFBLEtBQUssQ0FBQ3FDLElBQU4sQ0FBVyxFQUFYO0FBQ0FuQyxJQUFBQSxVQUFVLENBQUNtQyxJQUFYLENBQWdCLElBQWhCO0FBQ0Q7O0FBQ0QsT0FBSyxJQUFJQyxFQUFFLEdBQUcsQ0FBZCxFQUFpQkEsRUFBRSxHQUFHdEMsS0FBSyxDQUFDRixNQUFOLEdBQWUsQ0FBckMsRUFBd0N3QyxFQUFFLEVBQTFDLEVBQThDO0FBQzVDdEMsSUFBQUEsS0FBSyxDQUFDc0MsRUFBRCxDQUFMLEdBQVl0QyxLQUFLLENBQUNzQyxFQUFELENBQUwsR0FBWXBDLFVBQVUsQ0FBQ29DLEVBQUQsQ0FBbEM7QUFDRDs7QUFDRCxTQUFPdEMsS0FBSyxDQUFDdUMsSUFBTixDQUFXLEVBQVgsQ0FBUDtBQUNELEMsQ0FFRDs7O0FBQ08sU0FBU0MsWUFBVCxDQUFzQi9DLE9BQXRCLEVBQStCQyxPQUEvQixFQUF3QztBQUM3QyxNQUFJLE9BQU9ELE9BQVAsS0FBbUIsUUFBdkIsRUFBaUM7QUFDL0JBLElBQUFBLE9BQU87QUFBRztBQUFBO0FBQUE7O0FBQUFFO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUE7QUFBQSxLQUFXRixPQUFYLENBQVY7QUFDRDs7QUFFRCxNQUFJZ0QsWUFBWSxHQUFHLENBQW5COztBQUNBLFdBQVNDLFlBQVQsR0FBd0I7QUFDdEIsUUFBSUMsS0FBSyxHQUFHbEQsT0FBTyxDQUFDZ0QsWUFBWSxFQUFiLENBQW5COztBQUNBLFFBQUksQ0FBQ0UsS0FBTCxFQUFZO0FBQ1YsYUFBT2pELE9BQU8sQ0FBQ2tELFFBQVIsRUFBUDtBQUNEOztBQUVEbEQsSUFBQUEsT0FBTyxDQUFDbUQsUUFBUixDQUFpQkYsS0FBakIsRUFBd0IsVUFBU0csR0FBVCxFQUFjQyxJQUFkLEVBQW9CO0FBQzFDLFVBQUlELEdBQUosRUFBUztBQUNQLGVBQU9wRCxPQUFPLENBQUNrRCxRQUFSLENBQWlCRSxHQUFqQixDQUFQO0FBQ0Q7O0FBRUQsVUFBSUUsY0FBYyxHQUFHekQsVUFBVSxDQUFDd0QsSUFBRCxFQUFPSixLQUFQLEVBQWNqRCxPQUFkLENBQS9CO0FBQ0FBLE1BQUFBLE9BQU8sQ0FBQ3VELE9BQVIsQ0FBZ0JOLEtBQWhCLEVBQXVCSyxjQUF2QixFQUF1QyxVQUFTRixHQUFULEVBQWM7QUFDbkQsWUFBSUEsR0FBSixFQUFTO0FBQ1AsaUJBQU9wRCxPQUFPLENBQUNrRCxRQUFSLENBQWlCRSxHQUFqQixDQUFQO0FBQ0Q7O0FBRURKLFFBQUFBLFlBQVk7QUFDYixPQU5EO0FBT0QsS0FiRDtBQWNEOztBQUNEQSxFQUFBQSxZQUFZO0FBQ2IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge3BhcnNlUGF0Y2h9IGZyb20gJy4vcGFyc2UnO1xuaW1wb3J0IGRpc3RhbmNlSXRlcmF0b3IgZnJvbSAnLi4vdXRpbC9kaXN0YW5jZS1pdGVyYXRvcic7XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVBhdGNoKHNvdXJjZSwgdW5pRGlmZiwgb3B0aW9ucyA9IHt9KSB7XG4gIGlmICh0eXBlb2YgdW5pRGlmZiA9PT0gJ3N0cmluZycpIHtcbiAgICB1bmlEaWZmID0gcGFyc2VQYXRjaCh1bmlEaWZmKTtcbiAgfVxuXG4gIGlmIChBcnJheS5pc0FycmF5KHVuaURpZmYpKSB7XG4gICAgaWYgKHVuaURpZmYubGVuZ3RoID4gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdhcHBseVBhdGNoIG9ubHkgd29ya3Mgd2l0aCBhIHNpbmdsZSBpbnB1dC4nKTtcbiAgICB9XG5cbiAgICB1bmlEaWZmID0gdW5pRGlmZlswXTtcbiAgfVxuXG4gIC8vIEFwcGx5IHRoZSBkaWZmIHRvIHRoZSBpbnB1dFxuICBsZXQgbGluZXMgPSBzb3VyY2Uuc3BsaXQoL1xcclxcbnxbXFxuXFx2XFxmXFxyXFx4ODVdLyksXG4gICAgICBkZWxpbWl0ZXJzID0gc291cmNlLm1hdGNoKC9cXHJcXG58W1xcblxcdlxcZlxcclxceDg1XS9nKSB8fCBbXSxcbiAgICAgIGh1bmtzID0gdW5pRGlmZi5odW5rcyxcblxuICAgICAgY29tcGFyZUxpbmUgPSBvcHRpb25zLmNvbXBhcmVMaW5lIHx8ICgobGluZU51bWJlciwgbGluZSwgb3BlcmF0aW9uLCBwYXRjaENvbnRlbnQpID0+IGxpbmUgPT09IHBhdGNoQ29udGVudCksXG4gICAgICBlcnJvckNvdW50ID0gMCxcbiAgICAgIGZ1enpGYWN0b3IgPSBvcHRpb25zLmZ1enpGYWN0b3IgfHwgMCxcbiAgICAgIG1pbkxpbmUgPSAwLFxuICAgICAgb2Zmc2V0ID0gMCxcblxuICAgICAgcmVtb3ZlRU9GTkwsXG4gICAgICBhZGRFT0ZOTDtcblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoZSBodW5rIGV4YWN0bHkgZml0cyBvbiB0aGUgcHJvdmlkZWQgbG9jYXRpb25cbiAgICovXG4gIGZ1bmN0aW9uIGh1bmtGaXRzKGh1bmssIHRvUG9zKSB7XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBodW5rLmxpbmVzLmxlbmd0aDsgaisrKSB7XG4gICAgICBsZXQgbGluZSA9IGh1bmsubGluZXNbal0sXG4gICAgICAgICAgb3BlcmF0aW9uID0gKGxpbmUubGVuZ3RoID4gMCA/IGxpbmVbMF0gOiAnICcpLFxuICAgICAgICAgIGNvbnRlbnQgPSAobGluZS5sZW5ndGggPiAwID8gbGluZS5zdWJzdHIoMSkgOiBsaW5lKTtcblxuICAgICAgaWYgKG9wZXJhdGlvbiA9PT0gJyAnIHx8IG9wZXJhdGlvbiA9PT0gJy0nKSB7XG4gICAgICAgIC8vIENvbnRleHQgc2FuaXR5IGNoZWNrXG4gICAgICAgIGlmICghY29tcGFyZUxpbmUodG9Qb3MgKyAxLCBsaW5lc1t0b1Bvc10sIG9wZXJhdGlvbiwgY29udGVudCkpIHtcbiAgICAgICAgICBlcnJvckNvdW50Kys7XG5cbiAgICAgICAgICBpZiAoZXJyb3JDb3VudCA+IGZ1enpGYWN0b3IpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdG9Qb3MrKztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8vIFNlYXJjaCBiZXN0IGZpdCBvZmZzZXRzIGZvciBlYWNoIGh1bmsgYmFzZWQgb24gdGhlIHByZXZpb3VzIG9uZXNcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBodW5rcy5sZW5ndGg7IGkrKykge1xuICAgIGxldCBodW5rID0gaHVua3NbaV0sXG4gICAgICAgIG1heExpbmUgPSBsaW5lcy5sZW5ndGggLSBodW5rLm9sZExpbmVzLFxuICAgICAgICBsb2NhbE9mZnNldCA9IDAsXG4gICAgICAgIHRvUG9zID0gb2Zmc2V0ICsgaHVuay5vbGRTdGFydCAtIDE7XG5cbiAgICBsZXQgaXRlcmF0b3IgPSBkaXN0YW5jZUl0ZXJhdG9yKHRvUG9zLCBtaW5MaW5lLCBtYXhMaW5lKTtcblxuICAgIGZvciAoOyBsb2NhbE9mZnNldCAhPT0gdW5kZWZpbmVkOyBsb2NhbE9mZnNldCA9IGl0ZXJhdG9yKCkpIHtcbiAgICAgIGlmIChodW5rRml0cyhodW5rLCB0b1BvcyArIGxvY2FsT2Zmc2V0KSkge1xuICAgICAgICBodW5rLm9mZnNldCA9IG9mZnNldCArPSBsb2NhbE9mZnNldDtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGxvY2FsT2Zmc2V0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBTZXQgbG93ZXIgdGV4dCBsaW1pdCB0byBlbmQgb2YgdGhlIGN1cnJlbnQgaHVuaywgc28gbmV4dCBvbmVzIGRvbid0IHRyeVxuICAgIC8vIHRvIGZpdCBvdmVyIGFscmVhZHkgcGF0Y2hlZCB0ZXh0XG4gICAgbWluTGluZSA9IGh1bmsub2Zmc2V0ICsgaHVuay5vbGRTdGFydCArIGh1bmsub2xkTGluZXM7XG4gIH1cblxuICAvLyBBcHBseSBwYXRjaCBodW5rc1xuICBsZXQgZGlmZk9mZnNldCA9IDA7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaHVua3MubGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgaHVuayA9IGh1bmtzW2ldLFxuICAgICAgICB0b1BvcyA9IGh1bmsub2xkU3RhcnQgKyBodW5rLm9mZnNldCArIGRpZmZPZmZzZXQgLSAxO1xuICAgIGRpZmZPZmZzZXQgKz0gaHVuay5uZXdMaW5lcyAtIGh1bmsub2xkTGluZXM7XG5cbiAgICBpZiAodG9Qb3MgPCAwKSB7IC8vIENyZWF0aW5nIGEgbmV3IGZpbGVcbiAgICAgIHRvUG9zID0gMDtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGh1bmsubGluZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGxldCBsaW5lID0gaHVuay5saW5lc1tqXSxcbiAgICAgICAgICBvcGVyYXRpb24gPSAobGluZS5sZW5ndGggPiAwID8gbGluZVswXSA6ICcgJyksXG4gICAgICAgICAgY29udGVudCA9IChsaW5lLmxlbmd0aCA+IDAgPyBsaW5lLnN1YnN0cigxKSA6IGxpbmUpLFxuICAgICAgICAgIGRlbGltaXRlciA9IGh1bmsubGluZWRlbGltaXRlcnNbal07XG5cbiAgICAgIGlmIChvcGVyYXRpb24gPT09ICcgJykge1xuICAgICAgICB0b1BvcysrO1xuICAgICAgfSBlbHNlIGlmIChvcGVyYXRpb24gPT09ICctJykge1xuICAgICAgICBsaW5lcy5zcGxpY2UodG9Qb3MsIDEpO1xuICAgICAgICBkZWxpbWl0ZXJzLnNwbGljZSh0b1BvcywgMSk7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgfSBlbHNlIGlmIChvcGVyYXRpb24gPT09ICcrJykge1xuICAgICAgICBsaW5lcy5zcGxpY2UodG9Qb3MsIDAsIGNvbnRlbnQpO1xuICAgICAgICBkZWxpbWl0ZXJzLnNwbGljZSh0b1BvcywgMCwgZGVsaW1pdGVyKTtcbiAgICAgICAgdG9Qb3MrKztcbiAgICAgIH0gZWxzZSBpZiAob3BlcmF0aW9uID09PSAnXFxcXCcpIHtcbiAgICAgICAgbGV0IHByZXZpb3VzT3BlcmF0aW9uID0gaHVuay5saW5lc1tqIC0gMV0gPyBodW5rLmxpbmVzW2ogLSAxXVswXSA6IG51bGw7XG4gICAgICAgIGlmIChwcmV2aW91c09wZXJhdGlvbiA9PT0gJysnKSB7XG4gICAgICAgICAgcmVtb3ZlRU9GTkwgPSB0cnVlO1xuICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzT3BlcmF0aW9uID09PSAnLScpIHtcbiAgICAgICAgICBhZGRFT0ZOTCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBIYW5kbGUgRU9GTkwgaW5zZXJ0aW9uL3JlbW92YWxcbiAgaWYgKHJlbW92ZUVPRk5MKSB7XG4gICAgd2hpbGUgKCFsaW5lc1tsaW5lcy5sZW5ndGggLSAxXSkge1xuICAgICAgbGluZXMucG9wKCk7XG4gICAgICBkZWxpbWl0ZXJzLnBvcCgpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChhZGRFT0ZOTCkge1xuICAgIGxpbmVzLnB1c2goJycpO1xuICAgIGRlbGltaXRlcnMucHVzaCgnXFxuJyk7XG4gIH1cbiAgZm9yIChsZXQgX2sgPSAwOyBfayA8IGxpbmVzLmxlbmd0aCAtIDE7IF9rKyspIHtcbiAgICBsaW5lc1tfa10gPSBsaW5lc1tfa10gKyBkZWxpbWl0ZXJzW19rXTtcbiAgfVxuICByZXR1cm4gbGluZXMuam9pbignJyk7XG59XG5cbi8vIFdyYXBwZXIgdGhhdCBzdXBwb3J0cyBtdWx0aXBsZSBmaWxlIHBhdGNoZXMgdmlhIGNhbGxiYWNrcy5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVBhdGNoZXModW5pRGlmZiwgb3B0aW9ucykge1xuICBpZiAodHlwZW9mIHVuaURpZmYgPT09ICdzdHJpbmcnKSB7XG4gICAgdW5pRGlmZiA9IHBhcnNlUGF0Y2godW5pRGlmZik7XG4gIH1cblxuICBsZXQgY3VycmVudEluZGV4ID0gMDtcbiAgZnVuY3Rpb24gcHJvY2Vzc0luZGV4KCkge1xuICAgIGxldCBpbmRleCA9IHVuaURpZmZbY3VycmVudEluZGV4KytdO1xuICAgIGlmICghaW5kZXgpIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmNvbXBsZXRlKCk7XG4gICAgfVxuXG4gICAgb3B0aW9ucy5sb2FkRmlsZShpbmRleCwgZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIHJldHVybiBvcHRpb25zLmNvbXBsZXRlKGVycik7XG4gICAgICB9XG5cbiAgICAgIGxldCB1cGRhdGVkQ29udGVudCA9IGFwcGx5UGF0Y2goZGF0YSwgaW5kZXgsIG9wdGlvbnMpO1xuICAgICAgb3B0aW9ucy5wYXRjaGVkKGluZGV4LCB1cGRhdGVkQ29udGVudCwgZnVuY3Rpb24oZXJyKSB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gb3B0aW9ucy5jb21wbGV0ZShlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcHJvY2Vzc0luZGV4KCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuICBwcm9jZXNzSW5kZXgoKTtcbn1cbiJdfQ==
diff --git a/node_modules/libtap/node_modules/diff/lib/patch/create.js b/node_modules/libtap/node_modules/diff/lib/patch/create.js
new file mode 100644
index 0000000000000..d1717feb5a738
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/patch/create.js
@@ -0,0 +1,247 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.structuredPatch = structuredPatch;
+exports.createTwoFilesPatch = createTwoFilesPatch;
+exports.createPatch = createPatch;
+
+/*istanbul ignore end*/
+var
+/*istanbul ignore start*/
+_line = require("../diff/line")
+/*istanbul ignore end*/
+;
+
+/*istanbul ignore start*/ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
+
+function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
+
+function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
+
+function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
+
+/*istanbul ignore end*/
+function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
+  if (!options) {
+    options = {};
+  }
+
+  if (typeof options.context === 'undefined') {
+    options.context = 4;
+  }
+
+  var diff =
+  /*istanbul ignore start*/
+  (0,
+  /*istanbul ignore end*/
+
+  /*istanbul ignore start*/
+  _line
+  /*istanbul ignore end*/
+  .
+  /*istanbul ignore start*/
+  diffLines)
+  /*istanbul ignore end*/
+  (oldStr, newStr, options);
+  diff.push({
+    value: '',
+    lines: []
+  }); // Append an empty value to make cleanup easier
+
+  function contextLines(lines) {
+    return lines.map(function (entry) {
+      return ' ' + entry;
+    });
+  }
+
+  var hunks = [];
+  var oldRangeStart = 0,
+      newRangeStart = 0,
+      curRange = [],
+      oldLine = 1,
+      newLine = 1;
+
+  /*istanbul ignore start*/
+  var _loop = function _loop(
+  /*istanbul ignore end*/
+  i) {
+    var current = diff[i],
+        lines = current.lines || current.value.replace(/\n$/, '').split('\n');
+    current.lines = lines;
+
+    if (current.added || current.removed) {
+      /*istanbul ignore start*/
+      var _curRange;
+
+      /*istanbul ignore end*/
+      // If we have previous context, start with that
+      if (!oldRangeStart) {
+        var prev = diff[i - 1];
+        oldRangeStart = oldLine;
+        newRangeStart = newLine;
+
+        if (prev) {
+          curRange = options.context > 0 ? contextLines(prev.lines.slice(-options.context)) : [];
+          oldRangeStart -= curRange.length;
+          newRangeStart -= curRange.length;
+        }
+      } // Output our changes
+
+
+      /*istanbul ignore start*/
+      (_curRange =
+      /*istanbul ignore end*/
+      curRange).push.
+      /*istanbul ignore start*/
+      apply
+      /*istanbul ignore end*/
+      (
+      /*istanbul ignore start*/
+      _curRange
+      /*istanbul ignore end*/
+      ,
+      /*istanbul ignore start*/
+      _toConsumableArray(
+      /*istanbul ignore end*/
+      lines.map(function (entry) {
+        return (current.added ? '+' : '-') + entry;
+      }))); // Track the updated file position
+
+
+      if (current.added) {
+        newLine += lines.length;
+      } else {
+        oldLine += lines.length;
+      }
+    } else {
+      // Identical context lines. Track line changes
+      if (oldRangeStart) {
+        // Close out any changes that have been output (or join overlapping)
+        if (lines.length <= options.context * 2 && i < diff.length - 2) {
+          /*istanbul ignore start*/
+          var _curRange2;
+
+          /*istanbul ignore end*/
+          // Overlapping
+
+          /*istanbul ignore start*/
+          (_curRange2 =
+          /*istanbul ignore end*/
+          curRange).push.
+          /*istanbul ignore start*/
+          apply
+          /*istanbul ignore end*/
+          (
+          /*istanbul ignore start*/
+          _curRange2
+          /*istanbul ignore end*/
+          ,
+          /*istanbul ignore start*/
+          _toConsumableArray(
+          /*istanbul ignore end*/
+          contextLines(lines)));
+        } else {
+          /*istanbul ignore start*/
+          var _curRange3;
+
+          /*istanbul ignore end*/
+          // end the range and output
+          var contextSize = Math.min(lines.length, options.context);
+
+          /*istanbul ignore start*/
+          (_curRange3 =
+          /*istanbul ignore end*/
+          curRange).push.
+          /*istanbul ignore start*/
+          apply
+          /*istanbul ignore end*/
+          (
+          /*istanbul ignore start*/
+          _curRange3
+          /*istanbul ignore end*/
+          ,
+          /*istanbul ignore start*/
+          _toConsumableArray(
+          /*istanbul ignore end*/
+          contextLines(lines.slice(0, contextSize))));
+
+          var hunk = {
+            oldStart: oldRangeStart,
+            oldLines: oldLine - oldRangeStart + contextSize,
+            newStart: newRangeStart,
+            newLines: newLine - newRangeStart + contextSize,
+            lines: curRange
+          };
+
+          if (i >= diff.length - 2 && lines.length <= options.context) {
+            // EOF is inside this hunk
+            var oldEOFNewline = /\n$/.test(oldStr);
+            var newEOFNewline = /\n$/.test(newStr);
+            var noNlBeforeAdds = lines.length == 0 && curRange.length > hunk.oldLines;
+
+            if (!oldEOFNewline && noNlBeforeAdds) {
+              // special case: old has no eol and no trailing context; no-nl can end up before adds
+              curRange.splice(hunk.oldLines, 0, '\\ No newline at end of file');
+            }
+
+            if (!oldEOFNewline && !noNlBeforeAdds || !newEOFNewline) {
+              curRange.push('\\ No newline at end of file');
+            }
+          }
+
+          hunks.push(hunk);
+          oldRangeStart = 0;
+          newRangeStart = 0;
+          curRange = [];
+        }
+      }
+
+      oldLine += lines.length;
+      newLine += lines.length;
+    }
+  };
+
+  for (var i = 0; i < diff.length; i++) {
+    /*istanbul ignore start*/
+    _loop(
+    /*istanbul ignore end*/
+    i);
+  }
+
+  return {
+    oldFileName: oldFileName,
+    newFileName: newFileName,
+    oldHeader: oldHeader,
+    newHeader: newHeader,
+    hunks: hunks
+  };
+}
+
+function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
+  var diff = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options);
+  var ret = [];
+
+  if (oldFileName == newFileName) {
+    ret.push('Index: ' + oldFileName);
+  }
+
+  ret.push('===================================================================');
+  ret.push('--- ' + diff.oldFileName + (typeof diff.oldHeader === 'undefined' ? '' : '\t' + diff.oldHeader));
+  ret.push('+++ ' + diff.newFileName + (typeof diff.newHeader === 'undefined' ? '' : '\t' + diff.newHeader));
+
+  for (var i = 0; i < diff.hunks.length; i++) {
+    var hunk = diff.hunks[i];
+    ret.push('@@ -' + hunk.oldStart + ',' + hunk.oldLines + ' +' + hunk.newStart + ',' + hunk.newLines + ' @@');
+    ret.push.apply(ret, hunk.lines);
+  }
+
+  return ret.join('\n') + '\n';
+}
+
+function createPatch(fileName, oldStr, newStr, oldHeader, newHeader, options) {
+  return createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader, options);
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYXRjaC9jcmVhdGUuanMiXSwibmFtZXMiOlsic3RydWN0dXJlZFBhdGNoIiwib2xkRmlsZU5hbWUiLCJuZXdGaWxlTmFtZSIsIm9sZFN0ciIsIm5ld1N0ciIsIm9sZEhlYWRlciIsIm5ld0hlYWRlciIsIm9wdGlvbnMiLCJjb250ZXh0IiwiZGlmZiIsImRpZmZMaW5lcyIsInB1c2giLCJ2YWx1ZSIsImxpbmVzIiwiY29udGV4dExpbmVzIiwibWFwIiwiZW50cnkiLCJodW5rcyIsIm9sZFJhbmdlU3RhcnQiLCJuZXdSYW5nZVN0YXJ0IiwiY3VyUmFuZ2UiLCJvbGRMaW5lIiwibmV3TGluZSIsImkiLCJjdXJyZW50IiwicmVwbGFjZSIsInNwbGl0IiwiYWRkZWQiLCJyZW1vdmVkIiwicHJldiIsInNsaWNlIiwibGVuZ3RoIiwiY29udGV4dFNpemUiLCJNYXRoIiwibWluIiwiaHVuayIsIm9sZFN0YXJ0Iiwib2xkTGluZXMiLCJuZXdTdGFydCIsIm5ld0xpbmVzIiwib2xkRU9GTmV3bGluZSIsInRlc3QiLCJuZXdFT0ZOZXdsaW5lIiwibm9ObEJlZm9yZUFkZHMiLCJzcGxpY2UiLCJjcmVhdGVUd29GaWxlc1BhdGNoIiwicmV0IiwiYXBwbHkiLCJqb2luIiwiY3JlYXRlUGF0Y2giLCJmaWxlTmFtZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOzs7Ozs7Ozs7OztBQUVPLFNBQVNBLGVBQVQsQ0FBeUJDLFdBQXpCLEVBQXNDQyxXQUF0QyxFQUFtREMsTUFBbkQsRUFBMkRDLE1BQTNELEVBQW1FQyxTQUFuRSxFQUE4RUMsU0FBOUUsRUFBeUZDLE9BQXpGLEVBQWtHO0FBQ3ZHLE1BQUksQ0FBQ0EsT0FBTCxFQUFjO0FBQ1pBLElBQUFBLE9BQU8sR0FBRyxFQUFWO0FBQ0Q7O0FBQ0QsTUFBSSxPQUFPQSxPQUFPLENBQUNDLE9BQWYsS0FBMkIsV0FBL0IsRUFBNEM7QUFDMUNELElBQUFBLE9BQU8sQ0FBQ0MsT0FBUixHQUFrQixDQUFsQjtBQUNEOztBQUVELE1BQU1DLElBQUk7QUFBRztBQUFBO0FBQUE7O0FBQUFDO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUFBO0FBQUE7QUFBQSxHQUFVUCxNQUFWLEVBQWtCQyxNQUFsQixFQUEwQkcsT0FBMUIsQ0FBYjtBQUNBRSxFQUFBQSxJQUFJLENBQUNFLElBQUwsQ0FBVTtBQUFDQyxJQUFBQSxLQUFLLEVBQUUsRUFBUjtBQUFZQyxJQUFBQSxLQUFLLEVBQUU7QUFBbkIsR0FBVixFQVR1RyxDQVNwRTs7QUFFbkMsV0FBU0MsWUFBVCxDQUFzQkQsS0FBdEIsRUFBNkI7QUFDM0IsV0FBT0EsS0FBSyxDQUFDRSxHQUFOLENBQVUsVUFBU0MsS0FBVCxFQUFnQjtBQUFFLGFBQU8sTUFBTUEsS0FBYjtBQUFxQixLQUFqRCxDQUFQO0FBQ0Q7O0FBRUQsTUFBSUMsS0FBSyxHQUFHLEVBQVo7QUFDQSxNQUFJQyxhQUFhLEdBQUcsQ0FBcEI7QUFBQSxNQUF1QkMsYUFBYSxHQUFHLENBQXZDO0FBQUEsTUFBMENDLFFBQVEsR0FBRyxFQUFyRDtBQUFBLE1BQ0lDLE9BQU8sR0FBRyxDQURkO0FBQUEsTUFDaUJDLE9BQU8sR0FBRyxDQUQzQjs7QUFoQnVHO0FBQUE7QUFBQTtBQWtCOUZDLEVBQUFBLENBbEI4RjtBQW1CckcsUUFBTUMsT0FBTyxHQUFHZixJQUFJLENBQUNjLENBQUQsQ0FBcEI7QUFBQSxRQUNNVixLQUFLLEdBQUdXLE9BQU8sQ0FBQ1gsS0FBUixJQUFpQlcsT0FBTyxDQUFDWixLQUFSLENBQWNhLE9BQWQsQ0FBc0IsS0FBdEIsRUFBNkIsRUFBN0IsRUFBaUNDLEtBQWpDLENBQXVDLElBQXZDLENBRC9CO0FBRUFGLElBQUFBLE9BQU8sQ0FBQ1gsS0FBUixHQUFnQkEsS0FBaEI7O0FBRUEsUUFBSVcsT0FBTyxDQUFDRyxLQUFSLElBQWlCSCxPQUFPLENBQUNJLE9BQTdCLEVBQXNDO0FBQUE7QUFBQTs7QUFBQTtBQUNwQztBQUNBLFVBQUksQ0FBQ1YsYUFBTCxFQUFvQjtBQUNsQixZQUFNVyxJQUFJLEdBQUdwQixJQUFJLENBQUNjLENBQUMsR0FBRyxDQUFMLENBQWpCO0FBQ0FMLFFBQUFBLGFBQWEsR0FBR0csT0FBaEI7QUFDQUYsUUFBQUEsYUFBYSxHQUFHRyxPQUFoQjs7QUFFQSxZQUFJTyxJQUFKLEVBQVU7QUFDUlQsVUFBQUEsUUFBUSxHQUFHYixPQUFPLENBQUNDLE9BQVIsR0FBa0IsQ0FBbEIsR0FBc0JNLFlBQVksQ0FBQ2UsSUFBSSxDQUFDaEIsS0FBTCxDQUFXaUIsS0FBWCxDQUFpQixDQUFDdkIsT0FBTyxDQUFDQyxPQUExQixDQUFELENBQWxDLEdBQXlFLEVBQXBGO0FBQ0FVLFVBQUFBLGFBQWEsSUFBSUUsUUFBUSxDQUFDVyxNQUExQjtBQUNBWixVQUFBQSxhQUFhLElBQUlDLFFBQVEsQ0FBQ1csTUFBMUI7QUFDRDtBQUNGLE9BWm1DLENBY3BDOzs7QUFDQTtBQUFBO0FBQUE7QUFBQVgsTUFBQUEsUUFBUSxFQUFDVCxJQUFUO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFrQkUsTUFBQUEsS0FBSyxDQUFDRSxHQUFOLENBQVUsVUFBU0MsS0FBVCxFQUFnQjtBQUMxQyxlQUFPLENBQUNRLE9BQU8sQ0FBQ0csS0FBUixHQUFnQixHQUFoQixHQUFzQixHQUF2QixJQUE4QlgsS0FBckM7QUFDRCxPQUZpQixDQUFsQixHQWZvQyxDQW1CcEM7OztBQUNBLFVBQUlRLE9BQU8sQ0FBQ0csS0FBWixFQUFtQjtBQUNqQkwsUUFBQUEsT0FBTyxJQUFJVCxLQUFLLENBQUNrQixNQUFqQjtBQUNELE9BRkQsTUFFTztBQUNMVixRQUFBQSxPQUFPLElBQUlSLEtBQUssQ0FBQ2tCLE1BQWpCO0FBQ0Q7QUFDRixLQXpCRCxNQXlCTztBQUNMO0FBQ0EsVUFBSWIsYUFBSixFQUFtQjtBQUNqQjtBQUNBLFlBQUlMLEtBQUssQ0FBQ2tCLE1BQU4sSUFBZ0J4QixPQUFPLENBQUNDLE9BQVIsR0FBa0IsQ0FBbEMsSUFBdUNlLENBQUMsR0FBR2QsSUFBSSxDQUFDc0IsTUFBTCxHQUFjLENBQTdELEVBQWdFO0FBQUE7QUFBQTs7QUFBQTtBQUM5RDs7QUFDQTtBQUFBO0FBQUE7QUFBQVgsVUFBQUEsUUFBUSxFQUFDVCxJQUFUO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFrQkcsVUFBQUEsWUFBWSxDQUFDRCxLQUFELENBQTlCO0FBQ0QsU0FIRCxNQUdPO0FBQUE7QUFBQTs7QUFBQTtBQUNMO0FBQ0EsY0FBSW1CLFdBQVcsR0FBR0MsSUFBSSxDQUFDQyxHQUFMLENBQVNyQixLQUFLLENBQUNrQixNQUFmLEVBQXVCeEIsT0FBTyxDQUFDQyxPQUEvQixDQUFsQjs7QUFDQTtBQUFBO0FBQUE7QUFBQVksVUFBQUEsUUFBUSxFQUFDVCxJQUFUO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFrQkcsVUFBQUEsWUFBWSxDQUFDRCxLQUFLLENBQUNpQixLQUFOLENBQVksQ0FBWixFQUFlRSxXQUFmLENBQUQsQ0FBOUI7O0FBRUEsY0FBSUcsSUFBSSxHQUFHO0FBQ1RDLFlBQUFBLFFBQVEsRUFBRWxCLGFBREQ7QUFFVG1CLFlBQUFBLFFBQVEsRUFBR2hCLE9BQU8sR0FBR0gsYUFBVixHQUEwQmMsV0FGNUI7QUFHVE0sWUFBQUEsUUFBUSxFQUFFbkIsYUFIRDtBQUlUb0IsWUFBQUEsUUFBUSxFQUFHakIsT0FBTyxHQUFHSCxhQUFWLEdBQTBCYSxXQUo1QjtBQUtUbkIsWUFBQUEsS0FBSyxFQUFFTztBQUxFLFdBQVg7O0FBT0EsY0FBSUcsQ0FBQyxJQUFJZCxJQUFJLENBQUNzQixNQUFMLEdBQWMsQ0FBbkIsSUFBd0JsQixLQUFLLENBQUNrQixNQUFOLElBQWdCeEIsT0FBTyxDQUFDQyxPQUFwRCxFQUE2RDtBQUMzRDtBQUNBLGdCQUFJZ0MsYUFBYSxHQUFLLEtBQUQsQ0FBUUMsSUFBUixDQUFhdEMsTUFBYixDQUFyQjtBQUNBLGdCQUFJdUMsYUFBYSxHQUFLLEtBQUQsQ0FBUUQsSUFBUixDQUFhckMsTUFBYixDQUFyQjtBQUNBLGdCQUFJdUMsY0FBYyxHQUFHOUIsS0FBSyxDQUFDa0IsTUFBTixJQUFnQixDQUFoQixJQUFxQlgsUUFBUSxDQUFDVyxNQUFULEdBQWtCSSxJQUFJLENBQUNFLFFBQWpFOztBQUNBLGdCQUFJLENBQUNHLGFBQUQsSUFBa0JHLGNBQXRCLEVBQXNDO0FBQ3BDO0FBQ0F2QixjQUFBQSxRQUFRLENBQUN3QixNQUFULENBQWdCVCxJQUFJLENBQUNFLFFBQXJCLEVBQStCLENBQS9CLEVBQWtDLDhCQUFsQztBQUNEOztBQUNELGdCQUFLLENBQUNHLGFBQUQsSUFBa0IsQ0FBQ0csY0FBcEIsSUFBdUMsQ0FBQ0QsYUFBNUMsRUFBMkQ7QUFDekR0QixjQUFBQSxRQUFRLENBQUNULElBQVQsQ0FBYyw4QkFBZDtBQUNEO0FBQ0Y7O0FBQ0RNLFVBQUFBLEtBQUssQ0FBQ04sSUFBTixDQUFXd0IsSUFBWDtBQUVBakIsVUFBQUEsYUFBYSxHQUFHLENBQWhCO0FBQ0FDLFVBQUFBLGFBQWEsR0FBRyxDQUFoQjtBQUNBQyxVQUFBQSxRQUFRLEdBQUcsRUFBWDtBQUNEO0FBQ0Y7O0FBQ0RDLE1BQUFBLE9BQU8sSUFBSVIsS0FBSyxDQUFDa0IsTUFBakI7QUFDQVQsTUFBQUEsT0FBTyxJQUFJVCxLQUFLLENBQUNrQixNQUFqQjtBQUNEO0FBekZvRzs7QUFrQnZHLE9BQUssSUFBSVIsQ0FBQyxHQUFHLENBQWIsRUFBZ0JBLENBQUMsR0FBR2QsSUFBSSxDQUFDc0IsTUFBekIsRUFBaUNSLENBQUMsRUFBbEMsRUFBc0M7QUFBQTtBQUFBO0FBQUE7QUFBN0JBLElBQUFBLENBQTZCO0FBd0VyQzs7QUFFRCxTQUFPO0FBQ0x0QixJQUFBQSxXQUFXLEVBQUVBLFdBRFI7QUFDcUJDLElBQUFBLFdBQVcsRUFBRUEsV0FEbEM7QUFFTEcsSUFBQUEsU0FBUyxFQUFFQSxTQUZOO0FBRWlCQyxJQUFBQSxTQUFTLEVBQUVBLFNBRjVCO0FBR0xXLElBQUFBLEtBQUssRUFBRUE7QUFIRixHQUFQO0FBS0Q7O0FBRU0sU0FBUzRCLG1CQUFULENBQTZCNUMsV0FBN0IsRUFBMENDLFdBQTFDLEVBQXVEQyxNQUF2RCxFQUErREMsTUFBL0QsRUFBdUVDLFNBQXZFLEVBQWtGQyxTQUFsRixFQUE2RkMsT0FBN0YsRUFBc0c7QUFDM0csTUFBTUUsSUFBSSxHQUFHVCxlQUFlLENBQUNDLFdBQUQsRUFBY0MsV0FBZCxFQUEyQkMsTUFBM0IsRUFBbUNDLE1BQW5DLEVBQTJDQyxTQUEzQyxFQUFzREMsU0FBdEQsRUFBaUVDLE9BQWpFLENBQTVCO0FBRUEsTUFBTXVDLEdBQUcsR0FBRyxFQUFaOztBQUNBLE1BQUk3QyxXQUFXLElBQUlDLFdBQW5CLEVBQWdDO0FBQzlCNEMsSUFBQUEsR0FBRyxDQUFDbkMsSUFBSixDQUFTLFlBQVlWLFdBQXJCO0FBQ0Q7O0FBQ0Q2QyxFQUFBQSxHQUFHLENBQUNuQyxJQUFKLENBQVMscUVBQVQ7QUFDQW1DLEVBQUFBLEdBQUcsQ0FBQ25DLElBQUosQ0FBUyxTQUFTRixJQUFJLENBQUNSLFdBQWQsSUFBNkIsT0FBT1EsSUFBSSxDQUFDSixTQUFaLEtBQTBCLFdBQTFCLEdBQXdDLEVBQXhDLEdBQTZDLE9BQU9JLElBQUksQ0FBQ0osU0FBdEYsQ0FBVDtBQUNBeUMsRUFBQUEsR0FBRyxDQUFDbkMsSUFBSixDQUFTLFNBQVNGLElBQUksQ0FBQ1AsV0FBZCxJQUE2QixPQUFPTyxJQUFJLENBQUNILFNBQVosS0FBMEIsV0FBMUIsR0FBd0MsRUFBeEMsR0FBNkMsT0FBT0csSUFBSSxDQUFDSCxTQUF0RixDQUFUOztBQUVBLE9BQUssSUFBSWlCLENBQUMsR0FBRyxDQUFiLEVBQWdCQSxDQUFDLEdBQUdkLElBQUksQ0FBQ1EsS0FBTCxDQUFXYyxNQUEvQixFQUF1Q1IsQ0FBQyxFQUF4QyxFQUE0QztBQUMxQyxRQUFNWSxJQUFJLEdBQUcxQixJQUFJLENBQUNRLEtBQUwsQ0FBV00sQ0FBWCxDQUFiO0FBQ0F1QixJQUFBQSxHQUFHLENBQUNuQyxJQUFKLENBQ0UsU0FBU3dCLElBQUksQ0FBQ0MsUUFBZCxHQUF5QixHQUF6QixHQUErQkQsSUFBSSxDQUFDRSxRQUFwQyxHQUNFLElBREYsR0FDU0YsSUFBSSxDQUFDRyxRQURkLEdBQ3lCLEdBRHpCLEdBQytCSCxJQUFJLENBQUNJLFFBRHBDLEdBRUUsS0FISjtBQUtBTyxJQUFBQSxHQUFHLENBQUNuQyxJQUFKLENBQVNvQyxLQUFULENBQWVELEdBQWYsRUFBb0JYLElBQUksQ0FBQ3RCLEtBQXpCO0FBQ0Q7O0FBRUQsU0FBT2lDLEdBQUcsQ0FBQ0UsSUFBSixDQUFTLElBQVQsSUFBaUIsSUFBeEI7QUFDRDs7QUFFTSxTQUFTQyxXQUFULENBQXFCQyxRQUFyQixFQUErQi9DLE1BQS9CLEVBQXVDQyxNQUF2QyxFQUErQ0MsU0FBL0MsRUFBMERDLFNBQTFELEVBQXFFQyxPQUFyRSxFQUE4RTtBQUNuRixTQUFPc0MsbUJBQW1CLENBQUNLLFFBQUQsRUFBV0EsUUFBWCxFQUFxQi9DLE1BQXJCLEVBQTZCQyxNQUE3QixFQUFxQ0MsU0FBckMsRUFBZ0RDLFNBQWhELEVBQTJEQyxPQUEzRCxDQUExQjtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtkaWZmTGluZXN9IGZyb20gJy4uL2RpZmYvbGluZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBzdHJ1Y3R1cmVkUGF0Y2gob2xkRmlsZU5hbWUsIG5ld0ZpbGVOYW1lLCBvbGRTdHIsIG5ld1N0ciwgb2xkSGVhZGVyLCBuZXdIZWFkZXIsIG9wdGlvbnMpIHtcbiAgaWYgKCFvcHRpb25zKSB7XG4gICAgb3B0aW9ucyA9IHt9O1xuICB9XG4gIGlmICh0eXBlb2Ygb3B0aW9ucy5jb250ZXh0ID09PSAndW5kZWZpbmVkJykge1xuICAgIG9wdGlvbnMuY29udGV4dCA9IDQ7XG4gIH1cblxuICBjb25zdCBkaWZmID0gZGlmZkxpbmVzKG9sZFN0ciwgbmV3U3RyLCBvcHRpb25zKTtcbiAgZGlmZi5wdXNoKHt2YWx1ZTogJycsIGxpbmVzOiBbXX0pOyAvLyBBcHBlbmQgYW4gZW1wdHkgdmFsdWUgdG8gbWFrZSBjbGVhbnVwIGVhc2llclxuXG4gIGZ1bmN0aW9uIGNvbnRleHRMaW5lcyhsaW5lcykge1xuICAgIHJldHVybiBsaW5lcy5tYXAoZnVuY3Rpb24oZW50cnkpIHsgcmV0dXJuICcgJyArIGVudHJ5OyB9KTtcbiAgfVxuXG4gIGxldCBodW5rcyA9IFtdO1xuICBsZXQgb2xkUmFuZ2VTdGFydCA9IDAsIG5ld1JhbmdlU3RhcnQgPSAwLCBjdXJSYW5nZSA9IFtdLFxuICAgICAgb2xkTGluZSA9IDEsIG5ld0xpbmUgPSAxO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGRpZmYubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBjdXJyZW50ID0gZGlmZltpXSxcbiAgICAgICAgICBsaW5lcyA9IGN1cnJlbnQubGluZXMgfHwgY3VycmVudC52YWx1ZS5yZXBsYWNlKC9cXG4kLywgJycpLnNwbGl0KCdcXG4nKTtcbiAgICBjdXJyZW50LmxpbmVzID0gbGluZXM7XG5cbiAgICBpZiAoY3VycmVudC5hZGRlZCB8fCBjdXJyZW50LnJlbW92ZWQpIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgcHJldmlvdXMgY29udGV4dCwgc3RhcnQgd2l0aCB0aGF0XG4gICAgICBpZiAoIW9sZFJhbmdlU3RhcnQpIHtcbiAgICAgICAgY29uc3QgcHJldiA9IGRpZmZbaSAtIDFdO1xuICAgICAgICBvbGRSYW5nZVN0YXJ0ID0gb2xkTGluZTtcbiAgICAgICAgbmV3UmFuZ2VTdGFydCA9IG5ld0xpbmU7XG5cbiAgICAgICAgaWYgKHByZXYpIHtcbiAgICAgICAgICBjdXJSYW5nZSA9IG9wdGlvbnMuY29udGV4dCA+IDAgPyBjb250ZXh0TGluZXMocHJldi5saW5lcy5zbGljZSgtb3B0aW9ucy5jb250ZXh0KSkgOiBbXTtcbiAgICAgICAgICBvbGRSYW5nZVN0YXJ0IC09IGN1clJhbmdlLmxlbmd0aDtcbiAgICAgICAgICBuZXdSYW5nZVN0YXJ0IC09IGN1clJhbmdlLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBPdXRwdXQgb3VyIGNoYW5nZXNcbiAgICAgIGN1clJhbmdlLnB1c2goLi4uIGxpbmVzLm1hcChmdW5jdGlvbihlbnRyeSkge1xuICAgICAgICByZXR1cm4gKGN1cnJlbnQuYWRkZWQgPyAnKycgOiAnLScpICsgZW50cnk7XG4gICAgICB9KSk7XG5cbiAgICAgIC8vIFRyYWNrIHRoZSB1cGRhdGVkIGZpbGUgcG9zaXRpb25cbiAgICAgIGlmIChjdXJyZW50LmFkZGVkKSB7XG4gICAgICAgIG5ld0xpbmUgKz0gbGluZXMubGVuZ3RoO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb2xkTGluZSArPSBsaW5lcy5sZW5ndGg7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElkZW50aWNhbCBjb250ZXh0IGxpbmVzLiBUcmFjayBsaW5lIGNoYW5nZXNcbiAgICAgIGlmIChvbGRSYW5nZVN0YXJ0KSB7XG4gICAgICAgIC8vIENsb3NlIG91dCBhbnkgY2hhbmdlcyB0aGF0IGhhdmUgYmVlbiBvdXRwdXQgKG9yIGpvaW4gb3ZlcmxhcHBpbmcpXG4gICAgICAgIGlmIChsaW5lcy5sZW5ndGggPD0gb3B0aW9ucy5jb250ZXh0ICogMiAmJiBpIDwgZGlmZi5sZW5ndGggLSAyKSB7XG4gICAgICAgICAgLy8gT3ZlcmxhcHBpbmdcbiAgICAgICAgICBjdXJSYW5nZS5wdXNoKC4uLiBjb250ZXh0TGluZXMobGluZXMpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBlbmQgdGhlIHJhbmdlIGFuZCBvdXRwdXRcbiAgICAgICAgICBsZXQgY29udGV4dFNpemUgPSBNYXRoLm1pbihsaW5lcy5sZW5ndGgsIG9wdGlvbnMuY29udGV4dCk7XG4gICAgICAgICAgY3VyUmFuZ2UucHVzaCguLi4gY29udGV4dExpbmVzKGxpbmVzLnNsaWNlKDAsIGNvbnRleHRTaXplKSkpO1xuXG4gICAgICAgICAgbGV0IGh1bmsgPSB7XG4gICAgICAgICAgICBvbGRTdGFydDogb2xkUmFuZ2VTdGFydCxcbiAgICAgICAgICAgIG9sZExpbmVzOiAob2xkTGluZSAtIG9sZFJhbmdlU3RhcnQgKyBjb250ZXh0U2l6ZSksXG4gICAgICAgICAgICBuZXdTdGFydDogbmV3UmFuZ2VTdGFydCxcbiAgICAgICAgICAgIG5ld0xpbmVzOiAobmV3TGluZSAtIG5ld1JhbmdlU3RhcnQgKyBjb250ZXh0U2l6ZSksXG4gICAgICAgICAgICBsaW5lczogY3VyUmFuZ2VcbiAgICAgICAgICB9O1xuICAgICAgICAgIGlmIChpID49IGRpZmYubGVuZ3RoIC0gMiAmJiBsaW5lcy5sZW5ndGggPD0gb3B0aW9ucy5jb250ZXh0KSB7XG4gICAgICAgICAgICAvLyBFT0YgaXMgaW5zaWRlIHRoaXMgaHVua1xuICAgICAgICAgICAgbGV0IG9sZEVPRk5ld2xpbmUgPSAoKC9cXG4kLykudGVzdChvbGRTdHIpKTtcbiAgICAgICAgICAgIGxldCBuZXdFT0ZOZXdsaW5lID0gKCgvXFxuJC8pLnRlc3QobmV3U3RyKSk7XG4gICAgICAgICAgICBsZXQgbm9ObEJlZm9yZUFkZHMgPSBsaW5lcy5sZW5ndGggPT0gMCAmJiBjdXJSYW5nZS5sZW5ndGggPiBodW5rLm9sZExpbmVzO1xuICAgICAgICAgICAgaWYgKCFvbGRFT0ZOZXdsaW5lICYmIG5vTmxCZWZvcmVBZGRzKSB7XG4gICAgICAgICAgICAgIC8vIHNwZWNpYWwgY2FzZTogb2xkIGhhcyBubyBlb2wgYW5kIG5vIHRyYWlsaW5nIGNvbnRleHQ7IG5vLW5sIGNhbiBlbmQgdXAgYmVmb3JlIGFkZHNcbiAgICAgICAgICAgICAgY3VyUmFuZ2Uuc3BsaWNlKGh1bmsub2xkTGluZXMsIDAsICdcXFxcIE5vIG5ld2xpbmUgYXQgZW5kIG9mIGZpbGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgoIW9sZEVPRk5ld2xpbmUgJiYgIW5vTmxCZWZvcmVBZGRzKSB8fCAhbmV3RU9GTmV3bGluZSkge1xuICAgICAgICAgICAgICBjdXJSYW5nZS5wdXNoKCdcXFxcIE5vIG5ld2xpbmUgYXQgZW5kIG9mIGZpbGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaHVua3MucHVzaChodW5rKTtcblxuICAgICAgICAgIG9sZFJhbmdlU3RhcnQgPSAwO1xuICAgICAgICAgIG5ld1JhbmdlU3RhcnQgPSAwO1xuICAgICAgICAgIGN1clJhbmdlID0gW107XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIG9sZExpbmUgKz0gbGluZXMubGVuZ3RoO1xuICAgICAgbmV3TGluZSArPSBsaW5lcy5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBvbGRGaWxlTmFtZTogb2xkRmlsZU5hbWUsIG5ld0ZpbGVOYW1lOiBuZXdGaWxlTmFtZSxcbiAgICBvbGRIZWFkZXI6IG9sZEhlYWRlciwgbmV3SGVhZGVyOiBuZXdIZWFkZXIsXG4gICAgaHVua3M6IGh1bmtzXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVUd29GaWxlc1BhdGNoKG9sZEZpbGVOYW1lLCBuZXdGaWxlTmFtZSwgb2xkU3RyLCBuZXdTdHIsIG9sZEhlYWRlciwgbmV3SGVhZGVyLCBvcHRpb25zKSB7XG4gIGNvbnN0IGRpZmYgPSBzdHJ1Y3R1cmVkUGF0Y2gob2xkRmlsZU5hbWUsIG5ld0ZpbGVOYW1lLCBvbGRTdHIsIG5ld1N0ciwgb2xkSGVhZGVyLCBuZXdIZWFkZXIsIG9wdGlvbnMpO1xuXG4gIGNvbnN0IHJldCA9IFtdO1xuICBpZiAob2xkRmlsZU5hbWUgPT0gbmV3RmlsZU5hbWUpIHtcbiAgICByZXQucHVzaCgnSW5kZXg6ICcgKyBvbGRGaWxlTmFtZSk7XG4gIH1cbiAgcmV0LnB1c2goJz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0nKTtcbiAgcmV0LnB1c2goJy0tLSAnICsgZGlmZi5vbGRGaWxlTmFtZSArICh0eXBlb2YgZGlmZi5vbGRIZWFkZXIgPT09ICd1bmRlZmluZWQnID8gJycgOiAnXFx0JyArIGRpZmYub2xkSGVhZGVyKSk7XG4gIHJldC5wdXNoKCcrKysgJyArIGRpZmYubmV3RmlsZU5hbWUgKyAodHlwZW9mIGRpZmYubmV3SGVhZGVyID09PSAndW5kZWZpbmVkJyA/ICcnIDogJ1xcdCcgKyBkaWZmLm5ld0hlYWRlcikpO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgZGlmZi5odW5rcy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGh1bmsgPSBkaWZmLmh1bmtzW2ldO1xuICAgIHJldC5wdXNoKFxuICAgICAgJ0BAIC0nICsgaHVuay5vbGRTdGFydCArICcsJyArIGh1bmsub2xkTGluZXNcbiAgICAgICsgJyArJyArIGh1bmsubmV3U3RhcnQgKyAnLCcgKyBodW5rLm5ld0xpbmVzXG4gICAgICArICcgQEAnXG4gICAgKTtcbiAgICByZXQucHVzaC5hcHBseShyZXQsIGh1bmsubGluZXMpO1xuICB9XG5cbiAgcmV0dXJuIHJldC5qb2luKCdcXG4nKSArICdcXG4nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUGF0Y2goZmlsZU5hbWUsIG9sZFN0ciwgbmV3U3RyLCBvbGRIZWFkZXIsIG5ld0hlYWRlciwgb3B0aW9ucykge1xuICByZXR1cm4gY3JlYXRlVHdvRmlsZXNQYXRjaChmaWxlTmFtZSwgZmlsZU5hbWUsIG9sZFN0ciwgbmV3U3RyLCBvbGRIZWFkZXIsIG5ld0hlYWRlciwgb3B0aW9ucyk7XG59XG4iXX0=
diff --git a/node_modules/libtap/node_modules/diff/lib/patch/merge.js b/node_modules/libtap/node_modules/diff/lib/patch/merge.js
new file mode 100644
index 0000000000000..bbd429a284c4f
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/patch/merge.js
@@ -0,0 +1,609 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.calcLineCount = calcLineCount;
+exports.merge = merge;
+
+/*istanbul ignore end*/
+var
+/*istanbul ignore start*/
+_create = require("./create")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_parse = require("./parse")
+/*istanbul ignore end*/
+;
+
+var
+/*istanbul ignore start*/
+_array = require("../util/array")
+/*istanbul ignore end*/
+;
+
+/*istanbul ignore start*/ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
+
+function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
+
+function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
+
+function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
+
+/*istanbul ignore end*/
+function calcLineCount(hunk) {
+  /*istanbul ignore start*/
+  var _calcOldNewLineCount =
+  /*istanbul ignore end*/
+  calcOldNewLineCount(hunk.lines),
+      oldLines = _calcOldNewLineCount.oldLines,
+      newLines = _calcOldNewLineCount.newLines;
+
+  if (oldLines !== undefined) {
+    hunk.oldLines = oldLines;
+  } else {
+    delete hunk.oldLines;
+  }
+
+  if (newLines !== undefined) {
+    hunk.newLines = newLines;
+  } else {
+    delete hunk.newLines;
+  }
+}
+
+function merge(mine, theirs, base) {
+  mine = loadPatch(mine, base);
+  theirs = loadPatch(theirs, base);
+  var ret = {}; // For index we just let it pass through as it doesn't have any necessary meaning.
+  // Leaving sanity checks on this to the API consumer that may know more about the
+  // meaning in their own context.
+
+  if (mine.index || theirs.index) {
+    ret.index = mine.index || theirs.index;
+  }
+
+  if (mine.newFileName || theirs.newFileName) {
+    if (!fileNameChanged(mine)) {
+      // No header or no change in ours, use theirs (and ours if theirs does not exist)
+      ret.oldFileName = theirs.oldFileName || mine.oldFileName;
+      ret.newFileName = theirs.newFileName || mine.newFileName;
+      ret.oldHeader = theirs.oldHeader || mine.oldHeader;
+      ret.newHeader = theirs.newHeader || mine.newHeader;
+    } else if (!fileNameChanged(theirs)) {
+      // No header or no change in theirs, use ours
+      ret.oldFileName = mine.oldFileName;
+      ret.newFileName = mine.newFileName;
+      ret.oldHeader = mine.oldHeader;
+      ret.newHeader = mine.newHeader;
+    } else {
+      // Both changed... figure it out
+      ret.oldFileName = selectField(ret, mine.oldFileName, theirs.oldFileName);
+      ret.newFileName = selectField(ret, mine.newFileName, theirs.newFileName);
+      ret.oldHeader = selectField(ret, mine.oldHeader, theirs.oldHeader);
+      ret.newHeader = selectField(ret, mine.newHeader, theirs.newHeader);
+    }
+  }
+
+  ret.hunks = [];
+  var mineIndex = 0,
+      theirsIndex = 0,
+      mineOffset = 0,
+      theirsOffset = 0;
+
+  while (mineIndex < mine.hunks.length || theirsIndex < theirs.hunks.length) {
+    var mineCurrent = mine.hunks[mineIndex] || {
+      oldStart: Infinity
+    },
+        theirsCurrent = theirs.hunks[theirsIndex] || {
+      oldStart: Infinity
+    };
+
+    if (hunkBefore(mineCurrent, theirsCurrent)) {
+      // This patch does not overlap with any of the others, yay.
+      ret.hunks.push(cloneHunk(mineCurrent, mineOffset));
+      mineIndex++;
+      theirsOffset += mineCurrent.newLines - mineCurrent.oldLines;
+    } else if (hunkBefore(theirsCurrent, mineCurrent)) {
+      // This patch does not overlap with any of the others, yay.
+      ret.hunks.push(cloneHunk(theirsCurrent, theirsOffset));
+      theirsIndex++;
+      mineOffset += theirsCurrent.newLines - theirsCurrent.oldLines;
+    } else {
+      // Overlap, merge as best we can
+      var mergedHunk = {
+        oldStart: Math.min(mineCurrent.oldStart, theirsCurrent.oldStart),
+        oldLines: 0,
+        newStart: Math.min(mineCurrent.newStart + mineOffset, theirsCurrent.oldStart + theirsOffset),
+        newLines: 0,
+        lines: []
+      };
+      mergeLines(mergedHunk, mineCurrent.oldStart, mineCurrent.lines, theirsCurrent.oldStart, theirsCurrent.lines);
+      theirsIndex++;
+      mineIndex++;
+      ret.hunks.push(mergedHunk);
+    }
+  }
+
+  return ret;
+}
+
+function loadPatch(param, base) {
+  if (typeof param === 'string') {
+    if (/^@@/m.test(param) || /^Index:/m.test(param)) {
+      return (
+        /*istanbul ignore start*/
+        (0,
+        /*istanbul ignore end*/
+
+        /*istanbul ignore start*/
+        _parse
+        /*istanbul ignore end*/
+        .
+        /*istanbul ignore start*/
+        parsePatch)
+        /*istanbul ignore end*/
+        (param)[0]
+      );
+    }
+
+    if (!base) {
+      throw new Error('Must provide a base reference or pass in a patch');
+    }
+
+    return (
+      /*istanbul ignore start*/
+      (0,
+      /*istanbul ignore end*/
+
+      /*istanbul ignore start*/
+      _create
+      /*istanbul ignore end*/
+      .
+      /*istanbul ignore start*/
+      structuredPatch)
+      /*istanbul ignore end*/
+      (undefined, undefined, base, param)
+    );
+  }
+
+  return param;
+}
+
+function fileNameChanged(patch) {
+  return patch.newFileName && patch.newFileName !== patch.oldFileName;
+}
+
+function selectField(index, mine, theirs) {
+  if (mine === theirs) {
+    return mine;
+  } else {
+    index.conflict = true;
+    return {
+      mine: mine,
+      theirs: theirs
+    };
+  }
+}
+
+function hunkBefore(test, check) {
+  return test.oldStart < check.oldStart && test.oldStart + test.oldLines < check.oldStart;
+}
+
+function cloneHunk(hunk, offset) {
+  return {
+    oldStart: hunk.oldStart,
+    oldLines: hunk.oldLines,
+    newStart: hunk.newStart + offset,
+    newLines: hunk.newLines,
+    lines: hunk.lines
+  };
+}
+
+function mergeLines(hunk, mineOffset, mineLines, theirOffset, theirLines) {
+  // This will generally result in a conflicted hunk, but there are cases where the context
+  // is the only overlap where we can successfully merge the content here.
+  var mine = {
+    offset: mineOffset,
+    lines: mineLines,
+    index: 0
+  },
+      their = {
+    offset: theirOffset,
+    lines: theirLines,
+    index: 0
+  }; // Handle any leading content
+
+  insertLeading(hunk, mine, their);
+  insertLeading(hunk, their, mine); // Now in the overlap content. Scan through and select the best changes from each.
+
+  while (mine.index < mine.lines.length && their.index < their.lines.length) {
+    var mineCurrent = mine.lines[mine.index],
+        theirCurrent = their.lines[their.index];
+
+    if ((mineCurrent[0] === '-' || mineCurrent[0] === '+') && (theirCurrent[0] === '-' || theirCurrent[0] === '+')) {
+      // Both modified ...
+      mutualChange(hunk, mine, their);
+    } else if (mineCurrent[0] === '+' && theirCurrent[0] === ' ') {
+      /*istanbul ignore start*/
+      var _hunk$lines;
+
+      /*istanbul ignore end*/
+      // Mine inserted
+
+      /*istanbul ignore start*/
+      (_hunk$lines =
+      /*istanbul ignore end*/
+      hunk.lines).push.
+      /*istanbul ignore start*/
+      apply
+      /*istanbul ignore end*/
+      (
+      /*istanbul ignore start*/
+      _hunk$lines
+      /*istanbul ignore end*/
+      ,
+      /*istanbul ignore start*/
+      _toConsumableArray(
+      /*istanbul ignore end*/
+      collectChange(mine)));
+    } else if (theirCurrent[0] === '+' && mineCurrent[0] === ' ') {
+      /*istanbul ignore start*/
+      var _hunk$lines2;
+
+      /*istanbul ignore end*/
+      // Theirs inserted
+
+      /*istanbul ignore start*/
+      (_hunk$lines2 =
+      /*istanbul ignore end*/
+      hunk.lines).push.
+      /*istanbul ignore start*/
+      apply
+      /*istanbul ignore end*/
+      (
+      /*istanbul ignore start*/
+      _hunk$lines2
+      /*istanbul ignore end*/
+      ,
+      /*istanbul ignore start*/
+      _toConsumableArray(
+      /*istanbul ignore end*/
+      collectChange(their)));
+    } else if (mineCurrent[0] === '-' && theirCurrent[0] === ' ') {
+      // Mine removed or edited
+      removal(hunk, mine, their);
+    } else if (theirCurrent[0] === '-' && mineCurrent[0] === ' ') {
+      // Their removed or edited
+      removal(hunk, their, mine, true);
+    } else if (mineCurrent === theirCurrent) {
+      // Context identity
+      hunk.lines.push(mineCurrent);
+      mine.index++;
+      their.index++;
+    } else {
+      // Context mismatch
+      conflict(hunk, collectChange(mine), collectChange(their));
+    }
+  } // Now push anything that may be remaining
+
+
+  insertTrailing(hunk, mine);
+  insertTrailing(hunk, their);
+  calcLineCount(hunk);
+}
+
+function mutualChange(hunk, mine, their) {
+  var myChanges = collectChange(mine),
+      theirChanges = collectChange(their);
+
+  if (allRemoves(myChanges) && allRemoves(theirChanges)) {
+    // Special case for remove changes that are supersets of one another
+    if (
+    /*istanbul ignore start*/
+    (0,
+    /*istanbul ignore end*/
+
+    /*istanbul ignore start*/
+    _array
+    /*istanbul ignore end*/
+    .
+    /*istanbul ignore start*/
+    arrayStartsWith)
+    /*istanbul ignore end*/
+    (myChanges, theirChanges) && skipRemoveSuperset(their, myChanges, myChanges.length - theirChanges.length)) {
+      /*istanbul ignore start*/
+      var _hunk$lines3;
+
+      /*istanbul ignore end*/
+
+      /*istanbul ignore start*/
+      (_hunk$lines3 =
+      /*istanbul ignore end*/
+      hunk.lines).push.
+      /*istanbul ignore start*/
+      apply
+      /*istanbul ignore end*/
+      (
+      /*istanbul ignore start*/
+      _hunk$lines3
+      /*istanbul ignore end*/
+      ,
+      /*istanbul ignore start*/
+      _toConsumableArray(
+      /*istanbul ignore end*/
+      myChanges));
+
+      return;
+    } else if (
+    /*istanbul ignore start*/
+    (0,
+    /*istanbul ignore end*/
+
+    /*istanbul ignore start*/
+    _array
+    /*istanbul ignore end*/
+    .
+    /*istanbul ignore start*/
+    arrayStartsWith)
+    /*istanbul ignore end*/
+    (theirChanges, myChanges) && skipRemoveSuperset(mine, theirChanges, theirChanges.length - myChanges.length)) {
+      /*istanbul ignore start*/
+      var _hunk$lines4;
+
+      /*istanbul ignore end*/
+
+      /*istanbul ignore start*/
+      (_hunk$lines4 =
+      /*istanbul ignore end*/
+      hunk.lines).push.
+      /*istanbul ignore start*/
+      apply
+      /*istanbul ignore end*/
+      (
+      /*istanbul ignore start*/
+      _hunk$lines4
+      /*istanbul ignore end*/
+      ,
+      /*istanbul ignore start*/
+      _toConsumableArray(
+      /*istanbul ignore end*/
+      theirChanges));
+
+      return;
+    }
+  } else if (
+  /*istanbul ignore start*/
+  (0,
+  /*istanbul ignore end*/
+
+  /*istanbul ignore start*/
+  _array
+  /*istanbul ignore end*/
+  .
+  /*istanbul ignore start*/
+  arrayEqual)
+  /*istanbul ignore end*/
+  (myChanges, theirChanges)) {
+    /*istanbul ignore start*/
+    var _hunk$lines5;
+
+    /*istanbul ignore end*/
+
+    /*istanbul ignore start*/
+    (_hunk$lines5 =
+    /*istanbul ignore end*/
+    hunk.lines).push.
+    /*istanbul ignore start*/
+    apply
+    /*istanbul ignore end*/
+    (
+    /*istanbul ignore start*/
+    _hunk$lines5
+    /*istanbul ignore end*/
+    ,
+    /*istanbul ignore start*/
+    _toConsumableArray(
+    /*istanbul ignore end*/
+    myChanges));
+
+    return;
+  }
+
+  conflict(hunk, myChanges, theirChanges);
+}
+
+function removal(hunk, mine, their, swap) {
+  var myChanges = collectChange(mine),
+      theirChanges = collectContext(their, myChanges);
+
+  if (theirChanges.merged) {
+    /*istanbul ignore start*/
+    var _hunk$lines6;
+
+    /*istanbul ignore end*/
+
+    /*istanbul ignore start*/
+    (_hunk$lines6 =
+    /*istanbul ignore end*/
+    hunk.lines).push.
+    /*istanbul ignore start*/
+    apply
+    /*istanbul ignore end*/
+    (
+    /*istanbul ignore start*/
+    _hunk$lines6
+    /*istanbul ignore end*/
+    ,
+    /*istanbul ignore start*/
+    _toConsumableArray(
+    /*istanbul ignore end*/
+    theirChanges.merged));
+  } else {
+    conflict(hunk, swap ? theirChanges : myChanges, swap ? myChanges : theirChanges);
+  }
+}
+
+function conflict(hunk, mine, their) {
+  hunk.conflict = true;
+  hunk.lines.push({
+    conflict: true,
+    mine: mine,
+    theirs: their
+  });
+}
+
+function insertLeading(hunk, insert, their) {
+  while (insert.offset < their.offset && insert.index < insert.lines.length) {
+    var line = insert.lines[insert.index++];
+    hunk.lines.push(line);
+    insert.offset++;
+  }
+}
+
+function insertTrailing(hunk, insert) {
+  while (insert.index < insert.lines.length) {
+    var line = insert.lines[insert.index++];
+    hunk.lines.push(line);
+  }
+}
+
+function collectChange(state) {
+  var ret = [],
+      operation = state.lines[state.index][0];
+
+  while (state.index < state.lines.length) {
+    var line = state.lines[state.index]; // Group additions that are immediately after subtractions and treat them as one "atomic" modify change.
+
+    if (operation === '-' && line[0] === '+') {
+      operation = '+';
+    }
+
+    if (operation === line[0]) {
+      ret.push(line);
+      state.index++;
+    } else {
+      break;
+    }
+  }
+
+  return ret;
+}
+
+function collectContext(state, matchChanges) {
+  var changes = [],
+      merged = [],
+      matchIndex = 0,
+      contextChanges = false,
+      conflicted = false;
+
+  while (matchIndex < matchChanges.length && state.index < state.lines.length) {
+    var change = state.lines[state.index],
+        match = matchChanges[matchIndex]; // Once we've hit our add, then we are done
+
+    if (match[0] === '+') {
+      break;
+    }
+
+    contextChanges = contextChanges || change[0] !== ' ';
+    merged.push(match);
+    matchIndex++; // Consume any additions in the other block as a conflict to attempt
+    // to pull in the remaining context after this
+
+    if (change[0] === '+') {
+      conflicted = true;
+
+      while (change[0] === '+') {
+        changes.push(change);
+        change = state.lines[++state.index];
+      }
+    }
+
+    if (match.substr(1) === change.substr(1)) {
+      changes.push(change);
+      state.index++;
+    } else {
+      conflicted = true;
+    }
+  }
+
+  if ((matchChanges[matchIndex] || '')[0] === '+' && contextChanges) {
+    conflicted = true;
+  }
+
+  if (conflicted) {
+    return changes;
+  }
+
+  while (matchIndex < matchChanges.length) {
+    merged.push(matchChanges[matchIndex++]);
+  }
+
+  return {
+    merged: merged,
+    changes: changes
+  };
+}
+
+function allRemoves(changes) {
+  return changes.reduce(function (prev, change) {
+    return prev && change[0] === '-';
+  }, true);
+}
+
+function skipRemoveSuperset(state, removeChanges, delta) {
+  for (var i = 0; i < delta; i++) {
+    var changeContent = removeChanges[removeChanges.length - delta + i].substr(1);
+
+    if (state.lines[state.index + i] !== ' ' + changeContent) {
+      return false;
+    }
+  }
+
+  state.index += delta;
+  return true;
+}
+
+function calcOldNewLineCount(lines) {
+  var oldLines = 0;
+  var newLines = 0;
+  lines.forEach(function (line) {
+    if (typeof line !== 'string') {
+      var myCount = calcOldNewLineCount(line.mine);
+      var theirCount = calcOldNewLineCount(line.theirs);
+
+      if (oldLines !== undefined) {
+        if (myCount.oldLines === theirCount.oldLines) {
+          oldLines += myCount.oldLines;
+        } else {
+          oldLines = undefined;
+        }
+      }
+
+      if (newLines !== undefined) {
+        if (myCount.newLines === theirCount.newLines) {
+          newLines += myCount.newLines;
+        } else {
+          newLines = undefined;
+        }
+      }
+    } else {
+      if (newLines !== undefined && (line[0] === '+' || line[0] === ' ')) {
+        newLines++;
+      }
+
+      if (oldLines !== undefined && (line[0] === '-' || line[0] === ' ')) {
+        oldLines++;
+      }
+    }
+  });
+  return {
+    oldLines: oldLines,
+    newLines: newLines
+  };
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYXRjaC9tZXJnZS5qcyJdLCJuYW1lcyI6WyJjYWxjTGluZUNvdW50IiwiaHVuayIsImNhbGNPbGROZXdMaW5lQ291bnQiLCJsaW5lcyIsIm9sZExpbmVzIiwibmV3TGluZXMiLCJ1bmRlZmluZWQiLCJtZXJnZSIsIm1pbmUiLCJ0aGVpcnMiLCJiYXNlIiwibG9hZFBhdGNoIiwicmV0IiwiaW5kZXgiLCJuZXdGaWxlTmFtZSIsImZpbGVOYW1lQ2hhbmdlZCIsIm9sZEZpbGVOYW1lIiwib2xkSGVhZGVyIiwibmV3SGVhZGVyIiwic2VsZWN0RmllbGQiLCJodW5rcyIsIm1pbmVJbmRleCIsInRoZWlyc0luZGV4IiwibWluZU9mZnNldCIsInRoZWlyc09mZnNldCIsImxlbmd0aCIsIm1pbmVDdXJyZW50Iiwib2xkU3RhcnQiLCJJbmZpbml0eSIsInRoZWlyc0N1cnJlbnQiLCJodW5rQmVmb3JlIiwicHVzaCIsImNsb25lSHVuayIsIm1lcmdlZEh1bmsiLCJNYXRoIiwibWluIiwibmV3U3RhcnQiLCJtZXJnZUxpbmVzIiwicGFyYW0iLCJ0ZXN0IiwicGFyc2VQYXRjaCIsIkVycm9yIiwic3RydWN0dXJlZFBhdGNoIiwicGF0Y2giLCJjb25mbGljdCIsImNoZWNrIiwib2Zmc2V0IiwibWluZUxpbmVzIiwidGhlaXJPZmZzZXQiLCJ0aGVpckxpbmVzIiwidGhlaXIiLCJpbnNlcnRMZWFkaW5nIiwidGhlaXJDdXJyZW50IiwibXV0dWFsQ2hhbmdlIiwiY29sbGVjdENoYW5nZSIsInJlbW92YWwiLCJpbnNlcnRUcmFpbGluZyIsIm15Q2hhbmdlcyIsInRoZWlyQ2hhbmdlcyIsImFsbFJlbW92ZXMiLCJhcnJheVN0YXJ0c1dpdGgiLCJza2lwUmVtb3ZlU3VwZXJzZXQiLCJhcnJheUVxdWFsIiwic3dhcCIsImNvbGxlY3RDb250ZXh0IiwibWVyZ2VkIiwiaW5zZXJ0IiwibGluZSIsInN0YXRlIiwib3BlcmF0aW9uIiwibWF0Y2hDaGFuZ2VzIiwiY2hhbmdlcyIsIm1hdGNoSW5kZXgiLCJjb250ZXh0Q2hhbmdlcyIsImNvbmZsaWN0ZWQiLCJjaGFuZ2UiLCJtYXRjaCIsInN1YnN0ciIsInJlZHVjZSIsInByZXYiLCJyZW1vdmVDaGFuZ2VzIiwiZGVsdGEiLCJpIiwiY2hhbmdlQ29udGVudCIsImZvckVhY2giLCJteUNvdW50IiwidGhlaXJDb3VudCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7O0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTs7QUFFQTtBQUFBO0FBQUE7QUFBQTtBQUFBOzs7Ozs7Ozs7OztBQUVPLFNBQVNBLGFBQVQsQ0FBdUJDLElBQXZCLEVBQTZCO0FBQUE7QUFBQTtBQUFBO0FBQ0xDLEVBQUFBLG1CQUFtQixDQUFDRCxJQUFJLENBQUNFLEtBQU4sQ0FEZDtBQUFBLE1BQzNCQyxRQUQyQix3QkFDM0JBLFFBRDJCO0FBQUEsTUFDakJDLFFBRGlCLHdCQUNqQkEsUUFEaUI7O0FBR2xDLE1BQUlELFFBQVEsS0FBS0UsU0FBakIsRUFBNEI7QUFDMUJMLElBQUFBLElBQUksQ0FBQ0csUUFBTCxHQUFnQkEsUUFBaEI7QUFDRCxHQUZELE1BRU87QUFDTCxXQUFPSCxJQUFJLENBQUNHLFFBQVo7QUFDRDs7QUFFRCxNQUFJQyxRQUFRLEtBQUtDLFNBQWpCLEVBQTRCO0FBQzFCTCxJQUFBQSxJQUFJLENBQUNJLFFBQUwsR0FBZ0JBLFFBQWhCO0FBQ0QsR0FGRCxNQUVPO0FBQ0wsV0FBT0osSUFBSSxDQUFDSSxRQUFaO0FBQ0Q7QUFDRjs7QUFFTSxTQUFTRSxLQUFULENBQWVDLElBQWYsRUFBcUJDLE1BQXJCLEVBQTZCQyxJQUE3QixFQUFtQztBQUN4Q0YsRUFBQUEsSUFBSSxHQUFHRyxTQUFTLENBQUNILElBQUQsRUFBT0UsSUFBUCxDQUFoQjtBQUNBRCxFQUFBQSxNQUFNLEdBQUdFLFNBQVMsQ0FBQ0YsTUFBRCxFQUFTQyxJQUFULENBQWxCO0FBRUEsTUFBSUUsR0FBRyxHQUFHLEVBQVYsQ0FKd0MsQ0FNeEM7QUFDQTtBQUNBOztBQUNBLE1BQUlKLElBQUksQ0FBQ0ssS0FBTCxJQUFjSixNQUFNLENBQUNJLEtBQXpCLEVBQWdDO0FBQzlCRCxJQUFBQSxHQUFHLENBQUNDLEtBQUosR0FBWUwsSUFBSSxDQUFDSyxLQUFMLElBQWNKLE1BQU0sQ0FBQ0ksS0FBakM7QUFDRDs7QUFFRCxNQUFJTCxJQUFJLENBQUNNLFdBQUwsSUFBb0JMLE1BQU0sQ0FBQ0ssV0FBL0IsRUFBNEM7QUFDMUMsUUFBSSxDQUFDQyxlQUFlLENBQUNQLElBQUQsQ0FBcEIsRUFBNEI7QUFDMUI7QUFDQUksTUFBQUEsR0FBRyxDQUFDSSxXQUFKLEdBQWtCUCxNQUFNLENBQUNPLFdBQVAsSUFBc0JSLElBQUksQ0FBQ1EsV0FBN0M7QUFDQUosTUFBQUEsR0FBRyxDQUFDRSxXQUFKLEdBQWtCTCxNQUFNLENBQUNLLFdBQVAsSUFBc0JOLElBQUksQ0FBQ00sV0FBN0M7QUFDQUYsTUFBQUEsR0FBRyxDQUFDSyxTQUFKLEdBQWdCUixNQUFNLENBQUNRLFNBQVAsSUFBb0JULElBQUksQ0FBQ1MsU0FBekM7QUFDQUwsTUFBQUEsR0FBRyxDQUFDTSxTQUFKLEdBQWdCVCxNQUFNLENBQUNTLFNBQVAsSUFBb0JWLElBQUksQ0FBQ1UsU0FBekM7QUFDRCxLQU5ELE1BTU8sSUFBSSxDQUFDSCxlQUFlLENBQUNOLE1BQUQsQ0FBcEIsRUFBOEI7QUFDbkM7QUFDQUcsTUFBQUEsR0FBRyxDQUFDSSxXQUFKLEdBQWtCUixJQUFJLENBQUNRLFdBQXZCO0FBQ0FKLE1BQUFBLEdBQUcsQ0FBQ0UsV0FBSixHQUFrQk4sSUFBSSxDQUFDTSxXQUF2QjtBQUNBRixNQUFBQSxHQUFHLENBQUNLLFNBQUosR0FBZ0JULElBQUksQ0FBQ1MsU0FBckI7QUFDQUwsTUFBQUEsR0FBRyxDQUFDTSxTQUFKLEdBQWdCVixJQUFJLENBQUNVLFNBQXJCO0FBQ0QsS0FOTSxNQU1BO0FBQ0w7QUFDQU4sTUFBQUEsR0FBRyxDQUFDSSxXQUFKLEdBQWtCRyxXQUFXLENBQUNQLEdBQUQsRUFBTUosSUFBSSxDQUFDUSxXQUFYLEVBQXdCUCxNQUFNLENBQUNPLFdBQS9CLENBQTdCO0FBQ0FKLE1BQUFBLEdBQUcsQ0FBQ0UsV0FBSixHQUFrQkssV0FBVyxDQUFDUCxHQUFELEVBQU1KLElBQUksQ0FBQ00sV0FBWCxFQUF3QkwsTUFBTSxDQUFDSyxXQUEvQixDQUE3QjtBQUNBRixNQUFBQSxHQUFHLENBQUNLLFNBQUosR0FBZ0JFLFdBQVcsQ0FBQ1AsR0FBRCxFQUFNSixJQUFJLENBQUNTLFNBQVgsRUFBc0JSLE1BQU0sQ0FBQ1EsU0FBN0IsQ0FBM0I7QUFDQUwsTUFBQUEsR0FBRyxDQUFDTSxTQUFKLEdBQWdCQyxXQUFXLENBQUNQLEdBQUQsRUFBTUosSUFBSSxDQUFDVSxTQUFYLEVBQXNCVCxNQUFNLENBQUNTLFNBQTdCLENBQTNCO0FBQ0Q7QUFDRjs7QUFFRE4sRUFBQUEsR0FBRyxDQUFDUSxLQUFKLEdBQVksRUFBWjtBQUVBLE1BQUlDLFNBQVMsR0FBRyxDQUFoQjtBQUFBLE1BQ0lDLFdBQVcsR0FBRyxDQURsQjtBQUFBLE1BRUlDLFVBQVUsR0FBRyxDQUZqQjtBQUFBLE1BR0lDLFlBQVksR0FBRyxDQUhuQjs7QUFLQSxTQUFPSCxTQUFTLEdBQUdiLElBQUksQ0FBQ1ksS0FBTCxDQUFXSyxNQUF2QixJQUFpQ0gsV0FBVyxHQUFHYixNQUFNLENBQUNXLEtBQVAsQ0FBYUssTUFBbkUsRUFBMkU7QUFDekUsUUFBSUMsV0FBVyxHQUFHbEIsSUFBSSxDQUFDWSxLQUFMLENBQVdDLFNBQVgsS0FBeUI7QUFBQ00sTUFBQUEsUUFBUSxFQUFFQztBQUFYLEtBQTNDO0FBQUEsUUFDSUMsYUFBYSxHQUFHcEIsTUFBTSxDQUFDVyxLQUFQLENBQWFFLFdBQWIsS0FBNkI7QUFBQ0ssTUFBQUEsUUFBUSxFQUFFQztBQUFYLEtBRGpEOztBQUdBLFFBQUlFLFVBQVUsQ0FBQ0osV0FBRCxFQUFjRyxhQUFkLENBQWQsRUFBNEM7QUFDMUM7QUFDQWpCLE1BQUFBLEdBQUcsQ0FBQ1EsS0FBSixDQUFVVyxJQUFWLENBQWVDLFNBQVMsQ0FBQ04sV0FBRCxFQUFjSCxVQUFkLENBQXhCO0FBQ0FGLE1BQUFBLFNBQVM7QUFDVEcsTUFBQUEsWUFBWSxJQUFJRSxXQUFXLENBQUNyQixRQUFaLEdBQXVCcUIsV0FBVyxDQUFDdEIsUUFBbkQ7QUFDRCxLQUxELE1BS08sSUFBSTBCLFVBQVUsQ0FBQ0QsYUFBRCxFQUFnQkgsV0FBaEIsQ0FBZCxFQUE0QztBQUNqRDtBQUNBZCxNQUFBQSxHQUFHLENBQUNRLEtBQUosQ0FBVVcsSUFBVixDQUFlQyxTQUFTLENBQUNILGFBQUQsRUFBZ0JMLFlBQWhCLENBQXhCO0FBQ0FGLE1BQUFBLFdBQVc7QUFDWEMsTUFBQUEsVUFBVSxJQUFJTSxhQUFhLENBQUN4QixRQUFkLEdBQXlCd0IsYUFBYSxDQUFDekIsUUFBckQ7QUFDRCxLQUxNLE1BS0E7QUFDTDtBQUNBLFVBQUk2QixVQUFVLEdBQUc7QUFDZk4sUUFBQUEsUUFBUSxFQUFFTyxJQUFJLENBQUNDLEdBQUwsQ0FBU1QsV0FBVyxDQUFDQyxRQUFyQixFQUErQkUsYUFBYSxDQUFDRixRQUE3QyxDQURLO0FBRWZ2QixRQUFBQSxRQUFRLEVBQUUsQ0FGSztBQUdmZ0MsUUFBQUEsUUFBUSxFQUFFRixJQUFJLENBQUNDLEdBQUwsQ0FBU1QsV0FBVyxDQUFDVSxRQUFaLEdBQXVCYixVQUFoQyxFQUE0Q00sYUFBYSxDQUFDRixRQUFkLEdBQXlCSCxZQUFyRSxDQUhLO0FBSWZuQixRQUFBQSxRQUFRLEVBQUUsQ0FKSztBQUtmRixRQUFBQSxLQUFLLEVBQUU7QUFMUSxPQUFqQjtBQU9Ba0MsTUFBQUEsVUFBVSxDQUFDSixVQUFELEVBQWFQLFdBQVcsQ0FBQ0MsUUFBekIsRUFBbUNELFdBQVcsQ0FBQ3ZCLEtBQS9DLEVBQXNEMEIsYUFBYSxDQUFDRixRQUFwRSxFQUE4RUUsYUFBYSxDQUFDMUIsS0FBNUYsQ0FBVjtBQUNBbUIsTUFBQUEsV0FBVztBQUNYRCxNQUFBQSxTQUFTO0FBRVRULE1BQUFBLEdBQUcsQ0FBQ1EsS0FBSixDQUFVVyxJQUFWLENBQWVFLFVBQWY7QUFDRDtBQUNGOztBQUVELFNBQU9yQixHQUFQO0FBQ0Q7O0FBRUQsU0FBU0QsU0FBVCxDQUFtQjJCLEtBQW5CLEVBQTBCNUIsSUFBMUIsRUFBZ0M7QUFDOUIsTUFBSSxPQUFPNEIsS0FBUCxLQUFpQixRQUFyQixFQUErQjtBQUM3QixRQUFLLE1BQUQsQ0FBU0MsSUFBVCxDQUFjRCxLQUFkLEtBQTBCLFVBQUQsQ0FBYUMsSUFBYixDQUFrQkQsS0FBbEIsQ0FBN0IsRUFBd0Q7QUFDdEQsYUFBTztBQUFBO0FBQUE7QUFBQTs7QUFBQUU7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQTtBQUFBLFNBQVdGLEtBQVgsRUFBa0IsQ0FBbEI7QUFBUDtBQUNEOztBQUVELFFBQUksQ0FBQzVCLElBQUwsRUFBVztBQUNULFlBQU0sSUFBSStCLEtBQUosQ0FBVSxrREFBVixDQUFOO0FBQ0Q7O0FBQ0QsV0FBTztBQUFBO0FBQUE7QUFBQTs7QUFBQUM7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQTtBQUFBLE9BQWdCcEMsU0FBaEIsRUFBMkJBLFNBQTNCLEVBQXNDSSxJQUF0QyxFQUE0QzRCLEtBQTVDO0FBQVA7QUFDRDs7QUFFRCxTQUFPQSxLQUFQO0FBQ0Q7O0FBRUQsU0FBU3ZCLGVBQVQsQ0FBeUI0QixLQUF6QixFQUFnQztBQUM5QixTQUFPQSxLQUFLLENBQUM3QixXQUFOLElBQXFCNkIsS0FBSyxDQUFDN0IsV0FBTixLQUFzQjZCLEtBQUssQ0FBQzNCLFdBQXhEO0FBQ0Q7O0FBRUQsU0FBU0csV0FBVCxDQUFxQk4sS0FBckIsRUFBNEJMLElBQTVCLEVBQWtDQyxNQUFsQyxFQUEwQztBQUN4QyxNQUFJRCxJQUFJLEtBQUtDLE1BQWIsRUFBcUI7QUFDbkIsV0FBT0QsSUFBUDtBQUNELEdBRkQsTUFFTztBQUNMSyxJQUFBQSxLQUFLLENBQUMrQixRQUFOLEdBQWlCLElBQWpCO0FBQ0EsV0FBTztBQUFDcEMsTUFBQUEsSUFBSSxFQUFKQSxJQUFEO0FBQU9DLE1BQUFBLE1BQU0sRUFBTkE7QUFBUCxLQUFQO0FBQ0Q7QUFDRjs7QUFFRCxTQUFTcUIsVUFBVCxDQUFvQlMsSUFBcEIsRUFBMEJNLEtBQTFCLEVBQWlDO0FBQy9CLFNBQU9OLElBQUksQ0FBQ1osUUFBTCxHQUFnQmtCLEtBQUssQ0FBQ2xCLFFBQXRCLElBQ0RZLElBQUksQ0FBQ1osUUFBTCxHQUFnQlksSUFBSSxDQUFDbkMsUUFBdEIsR0FBa0N5QyxLQUFLLENBQUNsQixRQUQ3QztBQUVEOztBQUVELFNBQVNLLFNBQVQsQ0FBbUIvQixJQUFuQixFQUF5QjZDLE1BQXpCLEVBQWlDO0FBQy9CLFNBQU87QUFDTG5CLElBQUFBLFFBQVEsRUFBRTFCLElBQUksQ0FBQzBCLFFBRFY7QUFDb0J2QixJQUFBQSxRQUFRLEVBQUVILElBQUksQ0FBQ0csUUFEbkM7QUFFTGdDLElBQUFBLFFBQVEsRUFBRW5DLElBQUksQ0FBQ21DLFFBQUwsR0FBZ0JVLE1BRnJCO0FBRTZCekMsSUFBQUEsUUFBUSxFQUFFSixJQUFJLENBQUNJLFFBRjVDO0FBR0xGLElBQUFBLEtBQUssRUFBRUYsSUFBSSxDQUFDRTtBQUhQLEdBQVA7QUFLRDs7QUFFRCxTQUFTa0MsVUFBVCxDQUFvQnBDLElBQXBCLEVBQTBCc0IsVUFBMUIsRUFBc0N3QixTQUF0QyxFQUFpREMsV0FBakQsRUFBOERDLFVBQTlELEVBQTBFO0FBQ3hFO0FBQ0E7QUFDQSxNQUFJekMsSUFBSSxHQUFHO0FBQUNzQyxJQUFBQSxNQUFNLEVBQUV2QixVQUFUO0FBQXFCcEIsSUFBQUEsS0FBSyxFQUFFNEMsU0FBNUI7QUFBdUNsQyxJQUFBQSxLQUFLLEVBQUU7QUFBOUMsR0FBWDtBQUFBLE1BQ0lxQyxLQUFLLEdBQUc7QUFBQ0osSUFBQUEsTUFBTSxFQUFFRSxXQUFUO0FBQXNCN0MsSUFBQUEsS0FBSyxFQUFFOEMsVUFBN0I7QUFBeUNwQyxJQUFBQSxLQUFLLEVBQUU7QUFBaEQsR0FEWixDQUh3RSxDQU14RTs7QUFDQXNDLEVBQUFBLGFBQWEsQ0FBQ2xELElBQUQsRUFBT08sSUFBUCxFQUFhMEMsS0FBYixDQUFiO0FBQ0FDLEVBQUFBLGFBQWEsQ0FBQ2xELElBQUQsRUFBT2lELEtBQVAsRUFBYzFDLElBQWQsQ0FBYixDQVJ3RSxDQVV4RTs7QUFDQSxTQUFPQSxJQUFJLENBQUNLLEtBQUwsR0FBYUwsSUFBSSxDQUFDTCxLQUFMLENBQVdzQixNQUF4QixJQUFrQ3lCLEtBQUssQ0FBQ3JDLEtBQU4sR0FBY3FDLEtBQUssQ0FBQy9DLEtBQU4sQ0FBWXNCLE1BQW5FLEVBQTJFO0FBQ3pFLFFBQUlDLFdBQVcsR0FBR2xCLElBQUksQ0FBQ0wsS0FBTCxDQUFXSyxJQUFJLENBQUNLLEtBQWhCLENBQWxCO0FBQUEsUUFDSXVDLFlBQVksR0FBR0YsS0FBSyxDQUFDL0MsS0FBTixDQUFZK0MsS0FBSyxDQUFDckMsS0FBbEIsQ0FEbkI7O0FBR0EsUUFBSSxDQUFDYSxXQUFXLENBQUMsQ0FBRCxDQUFYLEtBQW1CLEdBQW5CLElBQTBCQSxXQUFXLENBQUMsQ0FBRCxDQUFYLEtBQW1CLEdBQTlDLE1BQ0kwQixZQUFZLENBQUMsQ0FBRCxDQUFaLEtBQW9CLEdBQXBCLElBQTJCQSxZQUFZLENBQUMsQ0FBRCxDQUFaLEtBQW9CLEdBRG5ELENBQUosRUFDNkQ7QUFDM0Q7QUFDQUMsTUFBQUEsWUFBWSxDQUFDcEQsSUFBRCxFQUFPTyxJQUFQLEVBQWEwQyxLQUFiLENBQVo7QUFDRCxLQUpELE1BSU8sSUFBSXhCLFdBQVcsQ0FBQyxDQUFELENBQVgsS0FBbUIsR0FBbkIsSUFBMEIwQixZQUFZLENBQUMsQ0FBRCxDQUFaLEtBQW9CLEdBQWxELEVBQXVEO0FBQUE7QUFBQTs7QUFBQTtBQUM1RDs7QUFDQTtBQUFBO0FBQUE7QUFBQW5ELE1BQUFBLElBQUksQ0FBQ0UsS0FBTCxFQUFXNEIsSUFBWDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBb0J1QixNQUFBQSxhQUFhLENBQUM5QyxJQUFELENBQWpDO0FBQ0QsS0FITSxNQUdBLElBQUk0QyxZQUFZLENBQUMsQ0FBRCxDQUFaLEtBQW9CLEdBQXBCLElBQTJCMUIsV0FBVyxDQUFDLENBQUQsQ0FBWCxLQUFtQixHQUFsRCxFQUF1RDtBQUFBO0FBQUE7O0FBQUE7QUFDNUQ7O0FBQ0E7QUFBQTtBQUFBO0FBQUF6QixNQUFBQSxJQUFJLENBQUNFLEtBQUwsRUFBVzRCLElBQVg7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQW9CdUIsTUFBQUEsYUFBYSxDQUFDSixLQUFELENBQWpDO0FBQ0QsS0FITSxNQUdBLElBQUl4QixXQUFXLENBQUMsQ0FBRCxDQUFYLEtBQW1CLEdBQW5CLElBQTBCMEIsWUFBWSxDQUFDLENBQUQsQ0FBWixLQUFvQixHQUFsRCxFQUF1RDtBQUM1RDtBQUNBRyxNQUFBQSxPQUFPLENBQUN0RCxJQUFELEVBQU9PLElBQVAsRUFBYTBDLEtBQWIsQ0FBUDtBQUNELEtBSE0sTUFHQSxJQUFJRSxZQUFZLENBQUMsQ0FBRCxDQUFaLEtBQW9CLEdBQXBCLElBQTJCMUIsV0FBVyxDQUFDLENBQUQsQ0FBWCxLQUFtQixHQUFsRCxFQUF1RDtBQUM1RDtBQUNBNkIsTUFBQUEsT0FBTyxDQUFDdEQsSUFBRCxFQUFPaUQsS0FBUCxFQUFjMUMsSUFBZCxFQUFvQixJQUFwQixDQUFQO0FBQ0QsS0FITSxNQUdBLElBQUlrQixXQUFXLEtBQUswQixZQUFwQixFQUFrQztBQUN2QztBQUNBbkQsTUFBQUEsSUFBSSxDQUFDRSxLQUFMLENBQVc0QixJQUFYLENBQWdCTCxXQUFoQjtBQUNBbEIsTUFBQUEsSUFBSSxDQUFDSyxLQUFMO0FBQ0FxQyxNQUFBQSxLQUFLLENBQUNyQyxLQUFOO0FBQ0QsS0FMTSxNQUtBO0FBQ0w7QUFDQStCLE1BQUFBLFFBQVEsQ0FBQzNDLElBQUQsRUFBT3FELGFBQWEsQ0FBQzlDLElBQUQsQ0FBcEIsRUFBNEI4QyxhQUFhLENBQUNKLEtBQUQsQ0FBekMsQ0FBUjtBQUNEO0FBQ0YsR0F4Q3VFLENBMEN4RTs7O0FBQ0FNLEVBQUFBLGNBQWMsQ0FBQ3ZELElBQUQsRUFBT08sSUFBUCxDQUFkO0FBQ0FnRCxFQUFBQSxjQUFjLENBQUN2RCxJQUFELEVBQU9pRCxLQUFQLENBQWQ7QUFFQWxELEVBQUFBLGFBQWEsQ0FBQ0MsSUFBRCxDQUFiO0FBQ0Q7O0FBRUQsU0FBU29ELFlBQVQsQ0FBc0JwRCxJQUF0QixFQUE0Qk8sSUFBNUIsRUFBa0MwQyxLQUFsQyxFQUF5QztBQUN2QyxNQUFJTyxTQUFTLEdBQUdILGFBQWEsQ0FBQzlDLElBQUQsQ0FBN0I7QUFBQSxNQUNJa0QsWUFBWSxHQUFHSixhQUFhLENBQUNKLEtBQUQsQ0FEaEM7O0FBR0EsTUFBSVMsVUFBVSxDQUFDRixTQUFELENBQVYsSUFBeUJFLFVBQVUsQ0FBQ0QsWUFBRCxDQUF2QyxFQUF1RDtBQUNyRDtBQUNBO0FBQUk7QUFBQTtBQUFBOztBQUFBRTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBO0FBQUEsS0FBZ0JILFNBQWhCLEVBQTJCQyxZQUEzQixLQUNHRyxrQkFBa0IsQ0FBQ1gsS0FBRCxFQUFRTyxTQUFSLEVBQW1CQSxTQUFTLENBQUNoQyxNQUFWLEdBQW1CaUMsWUFBWSxDQUFDakMsTUFBbkQsQ0FEekIsRUFDcUY7QUFBQTtBQUFBOztBQUFBOztBQUNuRjtBQUFBO0FBQUE7QUFBQXhCLE1BQUFBLElBQUksQ0FBQ0UsS0FBTCxFQUFXNEIsSUFBWDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBb0IwQixNQUFBQSxTQUFwQjs7QUFDQTtBQUNELEtBSkQsTUFJTztBQUFJO0FBQUE7QUFBQTs7QUFBQUc7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQTtBQUFBLEtBQWdCRixZQUFoQixFQUE4QkQsU0FBOUIsS0FDSkksa0JBQWtCLENBQUNyRCxJQUFELEVBQU9rRCxZQUFQLEVBQXFCQSxZQUFZLENBQUNqQyxNQUFiLEdBQXNCZ0MsU0FBUyxDQUFDaEMsTUFBckQsQ0FEbEIsRUFDZ0Y7QUFBQTtBQUFBOztBQUFBOztBQUNyRjtBQUFBO0FBQUE7QUFBQXhCLE1BQUFBLElBQUksQ0FBQ0UsS0FBTCxFQUFXNEIsSUFBWDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBb0IyQixNQUFBQSxZQUFwQjs7QUFDQTtBQUNEO0FBQ0YsR0FYRCxNQVdPO0FBQUk7QUFBQTtBQUFBOztBQUFBSTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBQTtBQUFBO0FBQUEsR0FBV0wsU0FBWCxFQUFzQkMsWUFBdEIsQ0FBSixFQUF5QztBQUFBO0FBQUE7O0FBQUE7O0FBQzlDO0FBQUE7QUFBQTtBQUFBekQsSUFBQUEsSUFBSSxDQUFDRSxLQUFMLEVBQVc0QixJQUFYO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFvQjBCLElBQUFBLFNBQXBCOztBQUNBO0FBQ0Q7O0FBRURiLEVBQUFBLFFBQVEsQ0FBQzNDLElBQUQsRUFBT3dELFNBQVAsRUFBa0JDLFlBQWxCLENBQVI7QUFDRDs7QUFFRCxTQUFTSCxPQUFULENBQWlCdEQsSUFBakIsRUFBdUJPLElBQXZCLEVBQTZCMEMsS0FBN0IsRUFBb0NhLElBQXBDLEVBQTBDO0FBQ3hDLE1BQUlOLFNBQVMsR0FBR0gsYUFBYSxDQUFDOUMsSUFBRCxDQUE3QjtBQUFBLE1BQ0lrRCxZQUFZLEdBQUdNLGNBQWMsQ0FBQ2QsS0FBRCxFQUFRTyxTQUFSLENBRGpDOztBQUVBLE1BQUlDLFlBQVksQ0FBQ08sTUFBakIsRUFBeUI7QUFBQTtBQUFBOztBQUFBOztBQUN2QjtBQUFBO0FBQUE7QUFBQWhFLElBQUFBLElBQUksQ0FBQ0UsS0FBTCxFQUFXNEIsSUFBWDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBb0IyQixJQUFBQSxZQUFZLENBQUNPLE1BQWpDO0FBQ0QsR0FGRCxNQUVPO0FBQ0xyQixJQUFBQSxRQUFRLENBQUMzQyxJQUFELEVBQU84RCxJQUFJLEdBQUdMLFlBQUgsR0FBa0JELFNBQTdCLEVBQXdDTSxJQUFJLEdBQUdOLFNBQUgsR0FBZUMsWUFBM0QsQ0FBUjtBQUNEO0FBQ0Y7O0FBRUQsU0FBU2QsUUFBVCxDQUFrQjNDLElBQWxCLEVBQXdCTyxJQUF4QixFQUE4QjBDLEtBQTlCLEVBQXFDO0FBQ25DakQsRUFBQUEsSUFBSSxDQUFDMkMsUUFBTCxHQUFnQixJQUFoQjtBQUNBM0MsRUFBQUEsSUFBSSxDQUFDRSxLQUFMLENBQVc0QixJQUFYLENBQWdCO0FBQ2RhLElBQUFBLFFBQVEsRUFBRSxJQURJO0FBRWRwQyxJQUFBQSxJQUFJLEVBQUVBLElBRlE7QUFHZEMsSUFBQUEsTUFBTSxFQUFFeUM7QUFITSxHQUFoQjtBQUtEOztBQUVELFNBQVNDLGFBQVQsQ0FBdUJsRCxJQUF2QixFQUE2QmlFLE1BQTdCLEVBQXFDaEIsS0FBckMsRUFBNEM7QUFDMUMsU0FBT2dCLE1BQU0sQ0FBQ3BCLE1BQVAsR0FBZ0JJLEtBQUssQ0FBQ0osTUFBdEIsSUFBZ0NvQixNQUFNLENBQUNyRCxLQUFQLEdBQWVxRCxNQUFNLENBQUMvRCxLQUFQLENBQWFzQixNQUFuRSxFQUEyRTtBQUN6RSxRQUFJMEMsSUFBSSxHQUFHRCxNQUFNLENBQUMvRCxLQUFQLENBQWErRCxNQUFNLENBQUNyRCxLQUFQLEVBQWIsQ0FBWDtBQUNBWixJQUFBQSxJQUFJLENBQUNFLEtBQUwsQ0FBVzRCLElBQVgsQ0FBZ0JvQyxJQUFoQjtBQUNBRCxJQUFBQSxNQUFNLENBQUNwQixNQUFQO0FBQ0Q7QUFDRjs7QUFDRCxTQUFTVSxjQUFULENBQXdCdkQsSUFBeEIsRUFBOEJpRSxNQUE5QixFQUFzQztBQUNwQyxTQUFPQSxNQUFNLENBQUNyRCxLQUFQLEdBQWVxRCxNQUFNLENBQUMvRCxLQUFQLENBQWFzQixNQUFuQyxFQUEyQztBQUN6QyxRQUFJMEMsSUFBSSxHQUFHRCxNQUFNLENBQUMvRCxLQUFQLENBQWErRCxNQUFNLENBQUNyRCxLQUFQLEVBQWIsQ0FBWDtBQUNBWixJQUFBQSxJQUFJLENBQUNFLEtBQUwsQ0FBVzRCLElBQVgsQ0FBZ0JvQyxJQUFoQjtBQUNEO0FBQ0Y7O0FBRUQsU0FBU2IsYUFBVCxDQUF1QmMsS0FBdkIsRUFBOEI7QUFDNUIsTUFBSXhELEdBQUcsR0FBRyxFQUFWO0FBQUEsTUFDSXlELFNBQVMsR0FBR0QsS0FBSyxDQUFDakUsS0FBTixDQUFZaUUsS0FBSyxDQUFDdkQsS0FBbEIsRUFBeUIsQ0FBekIsQ0FEaEI7O0FBRUEsU0FBT3VELEtBQUssQ0FBQ3ZELEtBQU4sR0FBY3VELEtBQUssQ0FBQ2pFLEtBQU4sQ0FBWXNCLE1BQWpDLEVBQXlDO0FBQ3ZDLFFBQUkwQyxJQUFJLEdBQUdDLEtBQUssQ0FBQ2pFLEtBQU4sQ0FBWWlFLEtBQUssQ0FBQ3ZELEtBQWxCLENBQVgsQ0FEdUMsQ0FHdkM7O0FBQ0EsUUFBSXdELFNBQVMsS0FBSyxHQUFkLElBQXFCRixJQUFJLENBQUMsQ0FBRCxDQUFKLEtBQVksR0FBckMsRUFBMEM7QUFDeENFLE1BQUFBLFNBQVMsR0FBRyxHQUFaO0FBQ0Q7O0FBRUQsUUFBSUEsU0FBUyxLQUFLRixJQUFJLENBQUMsQ0FBRCxDQUF0QixFQUEyQjtBQUN6QnZELE1BQUFBLEdBQUcsQ0FBQ21CLElBQUosQ0FBU29DLElBQVQ7QUFDQUMsTUFBQUEsS0FBSyxDQUFDdkQsS0FBTjtBQUNELEtBSEQsTUFHTztBQUNMO0FBQ0Q7QUFDRjs7QUFFRCxTQUFPRCxHQUFQO0FBQ0Q7O0FBQ0QsU0FBU29ELGNBQVQsQ0FBd0JJLEtBQXhCLEVBQStCRSxZQUEvQixFQUE2QztBQUMzQyxNQUFJQyxPQUFPLEdBQUcsRUFBZDtBQUFBLE1BQ0lOLE1BQU0sR0FBRyxFQURiO0FBQUEsTUFFSU8sVUFBVSxHQUFHLENBRmpCO0FBQUEsTUFHSUMsY0FBYyxHQUFHLEtBSHJCO0FBQUEsTUFJSUMsVUFBVSxHQUFHLEtBSmpCOztBQUtBLFNBQU9GLFVBQVUsR0FBR0YsWUFBWSxDQUFDN0MsTUFBMUIsSUFDRTJDLEtBQUssQ0FBQ3ZELEtBQU4sR0FBY3VELEtBQUssQ0FBQ2pFLEtBQU4sQ0FBWXNCLE1BRG5DLEVBQzJDO0FBQ3pDLFFBQUlrRCxNQUFNLEdBQUdQLEtBQUssQ0FBQ2pFLEtBQU4sQ0FBWWlFLEtBQUssQ0FBQ3ZELEtBQWxCLENBQWI7QUFBQSxRQUNJK0QsS0FBSyxHQUFHTixZQUFZLENBQUNFLFVBQUQsQ0FEeEIsQ0FEeUMsQ0FJekM7O0FBQ0EsUUFBSUksS0FBSyxDQUFDLENBQUQsQ0FBTCxLQUFhLEdBQWpCLEVBQXNCO0FBQ3BCO0FBQ0Q7O0FBRURILElBQUFBLGNBQWMsR0FBR0EsY0FBYyxJQUFJRSxNQUFNLENBQUMsQ0FBRCxDQUFOLEtBQWMsR0FBakQ7QUFFQVYsSUFBQUEsTUFBTSxDQUFDbEMsSUFBUCxDQUFZNkMsS0FBWjtBQUNBSixJQUFBQSxVQUFVLEdBWitCLENBY3pDO0FBQ0E7O0FBQ0EsUUFBSUcsTUFBTSxDQUFDLENBQUQsQ0FBTixLQUFjLEdBQWxCLEVBQXVCO0FBQ3JCRCxNQUFBQSxVQUFVLEdBQUcsSUFBYjs7QUFFQSxhQUFPQyxNQUFNLENBQUMsQ0FBRCxDQUFOLEtBQWMsR0FBckIsRUFBMEI7QUFDeEJKLFFBQUFBLE9BQU8sQ0FBQ3hDLElBQVIsQ0FBYTRDLE1BQWI7QUFDQUEsUUFBQUEsTUFBTSxHQUFHUCxLQUFLLENBQUNqRSxLQUFOLENBQVksRUFBRWlFLEtBQUssQ0FBQ3ZELEtBQXBCLENBQVQ7QUFDRDtBQUNGOztBQUVELFFBQUkrRCxLQUFLLENBQUNDLE1BQU4sQ0FBYSxDQUFiLE1BQW9CRixNQUFNLENBQUNFLE1BQVAsQ0FBYyxDQUFkLENBQXhCLEVBQTBDO0FBQ3hDTixNQUFBQSxPQUFPLENBQUN4QyxJQUFSLENBQWE0QyxNQUFiO0FBQ0FQLE1BQUFBLEtBQUssQ0FBQ3ZELEtBQU47QUFDRCxLQUhELE1BR087QUFDTDZELE1BQUFBLFVBQVUsR0FBRyxJQUFiO0FBQ0Q7QUFDRjs7QUFFRCxNQUFJLENBQUNKLFlBQVksQ0FBQ0UsVUFBRCxDQUFaLElBQTRCLEVBQTdCLEVBQWlDLENBQWpDLE1BQXdDLEdBQXhDLElBQ0dDLGNBRFAsRUFDdUI7QUFDckJDLElBQUFBLFVBQVUsR0FBRyxJQUFiO0FBQ0Q7O0FBRUQsTUFBSUEsVUFBSixFQUFnQjtBQUNkLFdBQU9ILE9BQVA7QUFDRDs7QUFFRCxTQUFPQyxVQUFVLEdBQUdGLFlBQVksQ0FBQzdDLE1BQWpDLEVBQXlDO0FBQ3ZDd0MsSUFBQUEsTUFBTSxDQUFDbEMsSUFBUCxDQUFZdUMsWUFBWSxDQUFDRSxVQUFVLEVBQVgsQ0FBeEI7QUFDRDs7QUFFRCxTQUFPO0FBQ0xQLElBQUFBLE1BQU0sRUFBTkEsTUFESztBQUVMTSxJQUFBQSxPQUFPLEVBQVBBO0FBRkssR0FBUDtBQUlEOztBQUVELFNBQVNaLFVBQVQsQ0FBb0JZLE9BQXBCLEVBQTZCO0FBQzNCLFNBQU9BLE9BQU8sQ0FBQ08sTUFBUixDQUFlLFVBQVNDLElBQVQsRUFBZUosTUFBZixFQUF1QjtBQUMzQyxXQUFPSSxJQUFJLElBQUlKLE1BQU0sQ0FBQyxDQUFELENBQU4sS0FBYyxHQUE3QjtBQUNELEdBRk0sRUFFSixJQUZJLENBQVA7QUFHRDs7QUFDRCxTQUFTZCxrQkFBVCxDQUE0Qk8sS0FBNUIsRUFBbUNZLGFBQW5DLEVBQWtEQyxLQUFsRCxFQUF5RDtBQUN2RCxPQUFLLElBQUlDLENBQUMsR0FBRyxDQUFiLEVBQWdCQSxDQUFDLEdBQUdELEtBQXBCLEVBQTJCQyxDQUFDLEVBQTVCLEVBQWdDO0FBQzlCLFFBQUlDLGFBQWEsR0FBR0gsYUFBYSxDQUFDQSxhQUFhLENBQUN2RCxNQUFkLEdBQXVCd0QsS0FBdkIsR0FBK0JDLENBQWhDLENBQWIsQ0FBZ0RMLE1BQWhELENBQXVELENBQXZELENBQXBCOztBQUNBLFFBQUlULEtBQUssQ0FBQ2pFLEtBQU4sQ0FBWWlFLEtBQUssQ0FBQ3ZELEtBQU4sR0FBY3FFLENBQTFCLE1BQWlDLE1BQU1DLGFBQTNDLEVBQTBEO0FBQ3hELGFBQU8sS0FBUDtBQUNEO0FBQ0Y7O0FBRURmLEVBQUFBLEtBQUssQ0FBQ3ZELEtBQU4sSUFBZW9FLEtBQWY7QUFDQSxTQUFPLElBQVA7QUFDRDs7QUFFRCxTQUFTL0UsbUJBQVQsQ0FBNkJDLEtBQTdCLEVBQW9DO0FBQ2xDLE1BQUlDLFFBQVEsR0FBRyxDQUFmO0FBQ0EsTUFBSUMsUUFBUSxHQUFHLENBQWY7QUFFQUYsRUFBQUEsS0FBSyxDQUFDaUYsT0FBTixDQUFjLFVBQVNqQixJQUFULEVBQWU7QUFDM0IsUUFBSSxPQUFPQSxJQUFQLEtBQWdCLFFBQXBCLEVBQThCO0FBQzVCLFVBQUlrQixPQUFPLEdBQUduRixtQkFBbUIsQ0FBQ2lFLElBQUksQ0FBQzNELElBQU4sQ0FBakM7QUFDQSxVQUFJOEUsVUFBVSxHQUFHcEYsbUJBQW1CLENBQUNpRSxJQUFJLENBQUMxRCxNQUFOLENBQXBDOztBQUVBLFVBQUlMLFFBQVEsS0FBS0UsU0FBakIsRUFBNEI7QUFDMUIsWUFBSStFLE9BQU8sQ0FBQ2pGLFFBQVIsS0FBcUJrRixVQUFVLENBQUNsRixRQUFwQyxFQUE4QztBQUM1Q0EsVUFBQUEsUUFBUSxJQUFJaUYsT0FBTyxDQUFDakYsUUFBcEI7QUFDRCxTQUZELE1BRU87QUFDTEEsVUFBQUEsUUFBUSxHQUFHRSxTQUFYO0FBQ0Q7QUFDRjs7QUFFRCxVQUFJRCxRQUFRLEtBQUtDLFNBQWpCLEVBQTRCO0FBQzFCLFlBQUkrRSxPQUFPLENBQUNoRixRQUFSLEtBQXFCaUYsVUFBVSxDQUFDakYsUUFBcEMsRUFBOEM7QUFDNUNBLFVBQUFBLFFBQVEsSUFBSWdGLE9BQU8sQ0FBQ2hGLFFBQXBCO0FBQ0QsU0FGRCxNQUVPO0FBQ0xBLFVBQUFBLFFBQVEsR0FBR0MsU0FBWDtBQUNEO0FBQ0Y7QUFDRixLQW5CRCxNQW1CTztBQUNMLFVBQUlELFFBQVEsS0FBS0MsU0FBYixLQUEyQjZELElBQUksQ0FBQyxDQUFELENBQUosS0FBWSxHQUFaLElBQW1CQSxJQUFJLENBQUMsQ0FBRCxDQUFKLEtBQVksR0FBMUQsQ0FBSixFQUFvRTtBQUNsRTlELFFBQUFBLFFBQVE7QUFDVDs7QUFDRCxVQUFJRCxRQUFRLEtBQUtFLFNBQWIsS0FBMkI2RCxJQUFJLENBQUMsQ0FBRCxDQUFKLEtBQVksR0FBWixJQUFtQkEsSUFBSSxDQUFDLENBQUQsQ0FBSixLQUFZLEdBQTFELENBQUosRUFBb0U7QUFDbEUvRCxRQUFBQSxRQUFRO0FBQ1Q7QUFDRjtBQUNGLEdBNUJEO0FBOEJBLFNBQU87QUFBQ0EsSUFBQUEsUUFBUSxFQUFSQSxRQUFEO0FBQVdDLElBQUFBLFFBQVEsRUFBUkE7QUFBWCxHQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge3N0cnVjdHVyZWRQYXRjaH0gZnJvbSAnLi9jcmVhdGUnO1xuaW1wb3J0IHtwYXJzZVBhdGNofSBmcm9tICcuL3BhcnNlJztcblxuaW1wb3J0IHthcnJheUVxdWFsLCBhcnJheVN0YXJ0c1dpdGh9IGZyb20gJy4uL3V0aWwvYXJyYXknO1xuXG5leHBvcnQgZnVuY3Rpb24gY2FsY0xpbmVDb3VudChodW5rKSB7XG4gIGNvbnN0IHtvbGRMaW5lcywgbmV3TGluZXN9ID0gY2FsY09sZE5ld0xpbmVDb3VudChodW5rLmxpbmVzKTtcblxuICBpZiAob2xkTGluZXMgIT09IHVuZGVmaW5lZCkge1xuICAgIGh1bmsub2xkTGluZXMgPSBvbGRMaW5lcztcbiAgfSBlbHNlIHtcbiAgICBkZWxldGUgaHVuay5vbGRMaW5lcztcbiAgfVxuXG4gIGlmIChuZXdMaW5lcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaHVuay5uZXdMaW5lcyA9IG5ld0xpbmVzO1xuICB9IGVsc2Uge1xuICAgIGRlbGV0ZSBodW5rLm5ld0xpbmVzO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtZXJnZShtaW5lLCB0aGVpcnMsIGJhc2UpIHtcbiAgbWluZSA9IGxvYWRQYXRjaChtaW5lLCBiYXNlKTtcbiAgdGhlaXJzID0gbG9hZFBhdGNoKHRoZWlycywgYmFzZSk7XG5cbiAgbGV0IHJldCA9IHt9O1xuXG4gIC8vIEZvciBpbmRleCB3ZSBqdXN0IGxldCBpdCBwYXNzIHRocm91Z2ggYXMgaXQgZG9lc24ndCBoYXZlIGFueSBuZWNlc3NhcnkgbWVhbmluZy5cbiAgLy8gTGVhdmluZyBzYW5pdHkgY2hlY2tzIG9uIHRoaXMgdG8gdGhlIEFQSSBjb25zdW1lciB0aGF0IG1heSBrbm93IG1vcmUgYWJvdXQgdGhlXG4gIC8vIG1lYW5pbmcgaW4gdGhlaXIgb3duIGNvbnRleHQuXG4gIGlmIChtaW5lLmluZGV4IHx8IHRoZWlycy5pbmRleCkge1xuICAgIHJldC5pbmRleCA9IG1pbmUuaW5kZXggfHwgdGhlaXJzLmluZGV4O1xuICB9XG5cbiAgaWYgKG1pbmUubmV3RmlsZU5hbWUgfHwgdGhlaXJzLm5ld0ZpbGVOYW1lKSB7XG4gICAgaWYgKCFmaWxlTmFtZUNoYW5nZWQobWluZSkpIHtcbiAgICAgIC8vIE5vIGhlYWRlciBvciBubyBjaGFuZ2UgaW4gb3VycywgdXNlIHRoZWlycyAoYW5kIG91cnMgaWYgdGhlaXJzIGRvZXMgbm90IGV4aXN0KVxuICAgICAgcmV0Lm9sZEZpbGVOYW1lID0gdGhlaXJzLm9sZEZpbGVOYW1lIHx8IG1pbmUub2xkRmlsZU5hbWU7XG4gICAgICByZXQubmV3RmlsZU5hbWUgPSB0aGVpcnMubmV3RmlsZU5hbWUgfHwgbWluZS5uZXdGaWxlTmFtZTtcbiAgICAgIHJldC5vbGRIZWFkZXIgPSB0aGVpcnMub2xkSGVhZGVyIHx8IG1pbmUub2xkSGVhZGVyO1xuICAgICAgcmV0Lm5ld0hlYWRlciA9IHRoZWlycy5uZXdIZWFkZXIgfHwgbWluZS5uZXdIZWFkZXI7XG4gICAgfSBlbHNlIGlmICghZmlsZU5hbWVDaGFuZ2VkKHRoZWlycykpIHtcbiAgICAgIC8vIE5vIGhlYWRlciBvciBubyBjaGFuZ2UgaW4gdGhlaXJzLCB1c2Ugb3Vyc1xuICAgICAgcmV0Lm9sZEZpbGVOYW1lID0gbWluZS5vbGRGaWxlTmFtZTtcbiAgICAgIHJldC5uZXdGaWxlTmFtZSA9IG1pbmUubmV3RmlsZU5hbWU7XG4gICAgICByZXQub2xkSGVhZGVyID0gbWluZS5vbGRIZWFkZXI7XG4gICAgICByZXQubmV3SGVhZGVyID0gbWluZS5uZXdIZWFkZXI7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEJvdGggY2hhbmdlZC4uLiBmaWd1cmUgaXQgb3V0XG4gICAgICByZXQub2xkRmlsZU5hbWUgPSBzZWxlY3RGaWVsZChyZXQsIG1pbmUub2xkRmlsZU5hbWUsIHRoZWlycy5vbGRGaWxlTmFtZSk7XG4gICAgICByZXQubmV3RmlsZU5hbWUgPSBzZWxlY3RGaWVsZChyZXQsIG1pbmUubmV3RmlsZU5hbWUsIHRoZWlycy5uZXdGaWxlTmFtZSk7XG4gICAgICByZXQub2xkSGVhZGVyID0gc2VsZWN0RmllbGQocmV0LCBtaW5lLm9sZEhlYWRlciwgdGhlaXJzLm9sZEhlYWRlcik7XG4gICAgICByZXQubmV3SGVhZGVyID0gc2VsZWN0RmllbGQocmV0LCBtaW5lLm5ld0hlYWRlciwgdGhlaXJzLm5ld0hlYWRlcik7XG4gICAgfVxuICB9XG5cbiAgcmV0Lmh1bmtzID0gW107XG5cbiAgbGV0IG1pbmVJbmRleCA9IDAsXG4gICAgICB0aGVpcnNJbmRleCA9IDAsXG4gICAgICBtaW5lT2Zmc2V0ID0gMCxcbiAgICAgIHRoZWlyc09mZnNldCA9IDA7XG5cbiAgd2hpbGUgKG1pbmVJbmRleCA8IG1pbmUuaHVua3MubGVuZ3RoIHx8IHRoZWlyc0luZGV4IDwgdGhlaXJzLmh1bmtzLmxlbmd0aCkge1xuICAgIGxldCBtaW5lQ3VycmVudCA9IG1pbmUuaHVua3NbbWluZUluZGV4XSB8fCB7b2xkU3RhcnQ6IEluZmluaXR5fSxcbiAgICAgICAgdGhlaXJzQ3VycmVudCA9IHRoZWlycy5odW5rc1t0aGVpcnNJbmRleF0gfHwge29sZFN0YXJ0OiBJbmZpbml0eX07XG5cbiAgICBpZiAoaHVua0JlZm9yZShtaW5lQ3VycmVudCwgdGhlaXJzQ3VycmVudCkpIHtcbiAgICAgIC8vIFRoaXMgcGF0Y2ggZG9lcyBub3Qgb3ZlcmxhcCB3aXRoIGFueSBvZiB0aGUgb3RoZXJzLCB5YXkuXG4gICAgICByZXQuaHVua3MucHVzaChjbG9uZUh1bmsobWluZUN1cnJlbnQsIG1pbmVPZmZzZXQpKTtcbiAgICAgIG1pbmVJbmRleCsrO1xuICAgICAgdGhlaXJzT2Zmc2V0ICs9IG1pbmVDdXJyZW50Lm5ld0xpbmVzIC0gbWluZUN1cnJlbnQub2xkTGluZXM7XG4gICAgfSBlbHNlIGlmIChodW5rQmVmb3JlKHRoZWlyc0N1cnJlbnQsIG1pbmVDdXJyZW50KSkge1xuICAgICAgLy8gVGhpcyBwYXRjaCBkb2VzIG5vdCBvdmVybGFwIHdpdGggYW55IG9mIHRoZSBvdGhlcnMsIHlheS5cbiAgICAgIHJldC5odW5rcy5wdXNoKGNsb25lSHVuayh0aGVpcnNDdXJyZW50LCB0aGVpcnNPZmZzZXQpKTtcbiAgICAgIHRoZWlyc0luZGV4Kys7XG4gICAgICBtaW5lT2Zmc2V0ICs9IHRoZWlyc0N1cnJlbnQubmV3TGluZXMgLSB0aGVpcnNDdXJyZW50Lm9sZExpbmVzO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBPdmVybGFwLCBtZXJnZSBhcyBiZXN0IHdlIGNhblxuICAgICAgbGV0IG1lcmdlZEh1bmsgPSB7XG4gICAgICAgIG9sZFN0YXJ0OiBNYXRoLm1pbihtaW5lQ3VycmVudC5vbGRTdGFydCwgdGhlaXJzQ3VycmVudC5vbGRTdGFydCksXG4gICAgICAgIG9sZExpbmVzOiAwLFxuICAgICAgICBuZXdTdGFydDogTWF0aC5taW4obWluZUN1cnJlbnQubmV3U3RhcnQgKyBtaW5lT2Zmc2V0LCB0aGVpcnNDdXJyZW50Lm9sZFN0YXJ0ICsgdGhlaXJzT2Zmc2V0KSxcbiAgICAgICAgbmV3TGluZXM6IDAsXG4gICAgICAgIGxpbmVzOiBbXVxuICAgICAgfTtcbiAgICAgIG1lcmdlTGluZXMobWVyZ2VkSHVuaywgbWluZUN1cnJlbnQub2xkU3RhcnQsIG1pbmVDdXJyZW50LmxpbmVzLCB0aGVpcnNDdXJyZW50Lm9sZFN0YXJ0LCB0aGVpcnNDdXJyZW50LmxpbmVzKTtcbiAgICAgIHRoZWlyc0luZGV4Kys7XG4gICAgICBtaW5lSW5kZXgrKztcblxuICAgICAgcmV0Lmh1bmtzLnB1c2gobWVyZ2VkSHVuayk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gbG9hZFBhdGNoKHBhcmFtLCBiYXNlKSB7XG4gIGlmICh0eXBlb2YgcGFyYW0gPT09ICdzdHJpbmcnKSB7XG4gICAgaWYgKCgvXkBAL20pLnRlc3QocGFyYW0pIHx8ICgoL15JbmRleDovbSkudGVzdChwYXJhbSkpKSB7XG4gICAgICByZXR1cm4gcGFyc2VQYXRjaChwYXJhbSlbMF07XG4gICAgfVxuXG4gICAgaWYgKCFiYXNlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ011c3QgcHJvdmlkZSBhIGJhc2UgcmVmZXJlbmNlIG9yIHBhc3MgaW4gYSBwYXRjaCcpO1xuICAgIH1cbiAgICByZXR1cm4gc3RydWN0dXJlZFBhdGNoKHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBiYXNlLCBwYXJhbSk7XG4gIH1cblxuICByZXR1cm4gcGFyYW07XG59XG5cbmZ1bmN0aW9uIGZpbGVOYW1lQ2hhbmdlZChwYXRjaCkge1xuICByZXR1cm4gcGF0Y2gubmV3RmlsZU5hbWUgJiYgcGF0Y2gubmV3RmlsZU5hbWUgIT09IHBhdGNoLm9sZEZpbGVOYW1lO1xufVxuXG5mdW5jdGlvbiBzZWxlY3RGaWVsZChpbmRleCwgbWluZSwgdGhlaXJzKSB7XG4gIGlmIChtaW5lID09PSB0aGVpcnMpIHtcbiAgICByZXR1cm4gbWluZTtcbiAgfSBlbHNlIHtcbiAgICBpbmRleC5jb25mbGljdCA9IHRydWU7XG4gICAgcmV0dXJuIHttaW5lLCB0aGVpcnN9O1xuICB9XG59XG5cbmZ1bmN0aW9uIGh1bmtCZWZvcmUodGVzdCwgY2hlY2spIHtcbiAgcmV0dXJuIHRlc3Qub2xkU3RhcnQgPCBjaGVjay5vbGRTdGFydFxuICAgICYmICh0ZXN0Lm9sZFN0YXJ0ICsgdGVzdC5vbGRMaW5lcykgPCBjaGVjay5vbGRTdGFydDtcbn1cblxuZnVuY3Rpb24gY2xvbmVIdW5rKGh1bmssIG9mZnNldCkge1xuICByZXR1cm4ge1xuICAgIG9sZFN0YXJ0OiBodW5rLm9sZFN0YXJ0LCBvbGRMaW5lczogaHVuay5vbGRMaW5lcyxcbiAgICBuZXdTdGFydDogaHVuay5uZXdTdGFydCArIG9mZnNldCwgbmV3TGluZXM6IGh1bmsubmV3TGluZXMsXG4gICAgbGluZXM6IGh1bmsubGluZXNcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWVyZ2VMaW5lcyhodW5rLCBtaW5lT2Zmc2V0LCBtaW5lTGluZXMsIHRoZWlyT2Zmc2V0LCB0aGVpckxpbmVzKSB7XG4gIC8vIFRoaXMgd2lsbCBnZW5lcmFsbHkgcmVzdWx0IGluIGEgY29uZmxpY3RlZCBodW5rLCBidXQgdGhlcmUgYXJlIGNhc2VzIHdoZXJlIHRoZSBjb250ZXh0XG4gIC8vIGlzIHRoZSBvbmx5IG92ZXJsYXAgd2hlcmUgd2UgY2FuIHN1Y2Nlc3NmdWxseSBtZXJnZSB0aGUgY29udGVudCBoZXJlLlxuICBsZXQgbWluZSA9IHtvZmZzZXQ6IG1pbmVPZmZzZXQsIGxpbmVzOiBtaW5lTGluZXMsIGluZGV4OiAwfSxcbiAgICAgIHRoZWlyID0ge29mZnNldDogdGhlaXJPZmZzZXQsIGxpbmVzOiB0aGVpckxpbmVzLCBpbmRleDogMH07XG5cbiAgLy8gSGFuZGxlIGFueSBsZWFkaW5nIGNvbnRlbnRcbiAgaW5zZXJ0TGVhZGluZyhodW5rLCBtaW5lLCB0aGVpcik7XG4gIGluc2VydExlYWRpbmcoaHVuaywgdGhlaXIsIG1pbmUpO1xuXG4gIC8vIE5vdyBpbiB0aGUgb3ZlcmxhcCBjb250ZW50LiBTY2FuIHRocm91Z2ggYW5kIHNlbGVjdCB0aGUgYmVzdCBjaGFuZ2VzIGZyb20gZWFjaC5cbiAgd2hpbGUgKG1pbmUuaW5kZXggPCBtaW5lLmxpbmVzLmxlbmd0aCAmJiB0aGVpci5pbmRleCA8IHRoZWlyLmxpbmVzLmxlbmd0aCkge1xuICAgIGxldCBtaW5lQ3VycmVudCA9IG1pbmUubGluZXNbbWluZS5pbmRleF0sXG4gICAgICAgIHRoZWlyQ3VycmVudCA9IHRoZWlyLmxpbmVzW3RoZWlyLmluZGV4XTtcblxuICAgIGlmICgobWluZUN1cnJlbnRbMF0gPT09ICctJyB8fCBtaW5lQ3VycmVudFswXSA9PT0gJysnKVxuICAgICAgICAmJiAodGhlaXJDdXJyZW50WzBdID09PSAnLScgfHwgdGhlaXJDdXJyZW50WzBdID09PSAnKycpKSB7XG4gICAgICAvLyBCb3RoIG1vZGlmaWVkIC4uLlxuICAgICAgbXV0dWFsQ2hhbmdlKGh1bmssIG1pbmUsIHRoZWlyKTtcbiAgICB9IGVsc2UgaWYgKG1pbmVDdXJyZW50WzBdID09PSAnKycgJiYgdGhlaXJDdXJyZW50WzBdID09PSAnICcpIHtcbiAgICAgIC8vIE1pbmUgaW5zZXJ0ZWRcbiAgICAgIGh1bmsubGluZXMucHVzaCguLi4gY29sbGVjdENoYW5nZShtaW5lKSk7XG4gICAgfSBlbHNlIGlmICh0aGVpckN1cnJlbnRbMF0gPT09ICcrJyAmJiBtaW5lQ3VycmVudFswXSA9PT0gJyAnKSB7XG4gICAgICAvLyBUaGVpcnMgaW5zZXJ0ZWRcbiAgICAgIGh1bmsubGluZXMucHVzaCguLi4gY29sbGVjdENoYW5nZSh0aGVpcikpO1xuICAgIH0gZWxzZSBpZiAobWluZUN1cnJlbnRbMF0gPT09ICctJyAmJiB0aGVpckN1cnJlbnRbMF0gPT09ICcgJykge1xuICAgICAgLy8gTWluZSByZW1vdmVkIG9yIGVkaXRlZFxuICAgICAgcmVtb3ZhbChodW5rLCBtaW5lLCB0aGVpcik7XG4gICAgfSBlbHNlIGlmICh0aGVpckN1cnJlbnRbMF0gPT09ICctJyAmJiBtaW5lQ3VycmVudFswXSA9PT0gJyAnKSB7XG4gICAgICAvLyBUaGVpciByZW1vdmVkIG9yIGVkaXRlZFxuICAgICAgcmVtb3ZhbChodW5rLCB0aGVpciwgbWluZSwgdHJ1ZSk7XG4gICAgfSBlbHNlIGlmIChtaW5lQ3VycmVudCA9PT0gdGhlaXJDdXJyZW50KSB7XG4gICAgICAvLyBDb250ZXh0IGlkZW50aXR5XG4gICAgICBodW5rLmxpbmVzLnB1c2gobWluZUN1cnJlbnQpO1xuICAgICAgbWluZS5pbmRleCsrO1xuICAgICAgdGhlaXIuaW5kZXgrKztcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQ29udGV4dCBtaXNtYXRjaFxuICAgICAgY29uZmxpY3QoaHVuaywgY29sbGVjdENoYW5nZShtaW5lKSwgY29sbGVjdENoYW5nZSh0aGVpcikpO1xuICAgIH1cbiAgfVxuXG4gIC8vIE5vdyBwdXNoIGFueXRoaW5nIHRoYXQgbWF5IGJlIHJlbWFpbmluZ1xuICBpbnNlcnRUcmFpbGluZyhodW5rLCBtaW5lKTtcbiAgaW5zZXJ0VHJhaWxpbmcoaHVuaywgdGhlaXIpO1xuXG4gIGNhbGNMaW5lQ291bnQoaHVuayk7XG59XG5cbmZ1bmN0aW9uIG11dHVhbENoYW5nZShodW5rLCBtaW5lLCB0aGVpcikge1xuICBsZXQgbXlDaGFuZ2VzID0gY29sbGVjdENoYW5nZShtaW5lKSxcbiAgICAgIHRoZWlyQ2hhbmdlcyA9IGNvbGxlY3RDaGFuZ2UodGhlaXIpO1xuXG4gIGlmIChhbGxSZW1vdmVzKG15Q2hhbmdlcykgJiYgYWxsUmVtb3Zlcyh0aGVpckNoYW5nZXMpKSB7XG4gICAgLy8gU3BlY2lhbCBjYXNlIGZvciByZW1vdmUgY2hhbmdlcyB0aGF0IGFyZSBzdXBlcnNldHMgb2Ygb25lIGFub3RoZXJcbiAgICBpZiAoYXJyYXlTdGFydHNXaXRoKG15Q2hhbmdlcywgdGhlaXJDaGFuZ2VzKVxuICAgICAgICAmJiBza2lwUmVtb3ZlU3VwZXJzZXQodGhlaXIsIG15Q2hhbmdlcywgbXlDaGFuZ2VzLmxlbmd0aCAtIHRoZWlyQ2hhbmdlcy5sZW5ndGgpKSB7XG4gICAgICBodW5rLmxpbmVzLnB1c2goLi4uIG15Q2hhbmdlcyk7XG4gICAgICByZXR1cm47XG4gICAgfSBlbHNlIGlmIChhcnJheVN0YXJ0c1dpdGgodGhlaXJDaGFuZ2VzLCBteUNoYW5nZXMpXG4gICAgICAgICYmIHNraXBSZW1vdmVTdXBlcnNldChtaW5lLCB0aGVpckNoYW5nZXMsIHRoZWlyQ2hhbmdlcy5sZW5ndGggLSBteUNoYW5nZXMubGVuZ3RoKSkge1xuICAgICAgaHVuay5saW5lcy5wdXNoKC4uLiB0aGVpckNoYW5nZXMpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfSBlbHNlIGlmIChhcnJheUVxdWFsKG15Q2hhbmdlcywgdGhlaXJDaGFuZ2VzKSkge1xuICAgIGh1bmsubGluZXMucHVzaCguLi4gbXlDaGFuZ2VzKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25mbGljdChodW5rLCBteUNoYW5nZXMsIHRoZWlyQ2hhbmdlcyk7XG59XG5cbmZ1bmN0aW9uIHJlbW92YWwoaHVuaywgbWluZSwgdGhlaXIsIHN3YXApIHtcbiAgbGV0IG15Q2hhbmdlcyA9IGNvbGxlY3RDaGFuZ2UobWluZSksXG4gICAgICB0aGVpckNoYW5nZXMgPSBjb2xsZWN0Q29udGV4dCh0aGVpciwgbXlDaGFuZ2VzKTtcbiAgaWYgKHRoZWlyQ2hhbmdlcy5tZXJnZWQpIHtcbiAgICBodW5rLmxpbmVzLnB1c2goLi4uIHRoZWlyQ2hhbmdlcy5tZXJnZWQpO1xuICB9IGVsc2Uge1xuICAgIGNvbmZsaWN0KGh1bmssIHN3YXAgPyB0aGVpckNoYW5nZXMgOiBteUNoYW5nZXMsIHN3YXAgPyBteUNoYW5nZXMgOiB0aGVpckNoYW5nZXMpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNvbmZsaWN0KGh1bmssIG1pbmUsIHRoZWlyKSB7XG4gIGh1bmsuY29uZmxpY3QgPSB0cnVlO1xuICBodW5rLmxpbmVzLnB1c2goe1xuICAgIGNvbmZsaWN0OiB0cnVlLFxuICAgIG1pbmU6IG1pbmUsXG4gICAgdGhlaXJzOiB0aGVpclxuICB9KTtcbn1cblxuZnVuY3Rpb24gaW5zZXJ0TGVhZGluZyhodW5rLCBpbnNlcnQsIHRoZWlyKSB7XG4gIHdoaWxlIChpbnNlcnQub2Zmc2V0IDwgdGhlaXIub2Zmc2V0ICYmIGluc2VydC5pbmRleCA8IGluc2VydC5saW5lcy5sZW5ndGgpIHtcbiAgICBsZXQgbGluZSA9IGluc2VydC5saW5lc1tpbnNlcnQuaW5kZXgrK107XG4gICAgaHVuay5saW5lcy5wdXNoKGxpbmUpO1xuICAgIGluc2VydC5vZmZzZXQrKztcbiAgfVxufVxuZnVuY3Rpb24gaW5zZXJ0VHJhaWxpbmcoaHVuaywgaW5zZXJ0KSB7XG4gIHdoaWxlIChpbnNlcnQuaW5kZXggPCBpbnNlcnQubGluZXMubGVuZ3RoKSB7XG4gICAgbGV0IGxpbmUgPSBpbnNlcnQubGluZXNbaW5zZXJ0LmluZGV4KytdO1xuICAgIGh1bmsubGluZXMucHVzaChsaW5lKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjb2xsZWN0Q2hhbmdlKHN0YXRlKSB7XG4gIGxldCByZXQgPSBbXSxcbiAgICAgIG9wZXJhdGlvbiA9IHN0YXRlLmxpbmVzW3N0YXRlLmluZGV4XVswXTtcbiAgd2hpbGUgKHN0YXRlLmluZGV4IDwgc3RhdGUubGluZXMubGVuZ3RoKSB7XG4gICAgbGV0IGxpbmUgPSBzdGF0ZS5saW5lc1tzdGF0ZS5pbmRleF07XG5cbiAgICAvLyBHcm91cCBhZGRpdGlvbnMgdGhhdCBhcmUgaW1tZWRpYXRlbHkgYWZ0ZXIgc3VidHJhY3Rpb25zIGFuZCB0cmVhdCB0aGVtIGFzIG9uZSBcImF0b21pY1wiIG1vZGlmeSBjaGFuZ2UuXG4gICAgaWYgKG9wZXJhdGlvbiA9PT0gJy0nICYmIGxpbmVbMF0gPT09ICcrJykge1xuICAgICAgb3BlcmF0aW9uID0gJysnO1xuICAgIH1cblxuICAgIGlmIChvcGVyYXRpb24gPT09IGxpbmVbMF0pIHtcbiAgICAgIHJldC5wdXNoKGxpbmUpO1xuICAgICAgc3RhdGUuaW5kZXgrKztcbiAgICB9IGVsc2Uge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cbmZ1bmN0aW9uIGNvbGxlY3RDb250ZXh0KHN0YXRlLCBtYXRjaENoYW5nZXMpIHtcbiAgbGV0IGNoYW5nZXMgPSBbXSxcbiAgICAgIG1lcmdlZCA9IFtdLFxuICAgICAgbWF0Y2hJbmRleCA9IDAsXG4gICAgICBjb250ZXh0Q2hhbmdlcyA9IGZhbHNlLFxuICAgICAgY29uZmxpY3RlZCA9IGZhbHNlO1xuICB3aGlsZSAobWF0Y2hJbmRleCA8IG1hdGNoQ2hhbmdlcy5sZW5ndGhcbiAgICAgICAgJiYgc3RhdGUuaW5kZXggPCBzdGF0ZS5saW5lcy5sZW5ndGgpIHtcbiAgICBsZXQgY2hhbmdlID0gc3RhdGUubGluZXNbc3RhdGUuaW5kZXhdLFxuICAgICAgICBtYXRjaCA9IG1hdGNoQ2hhbmdlc1ttYXRjaEluZGV4XTtcblxuICAgIC8vIE9uY2Ugd2UndmUgaGl0IG91ciBhZGQsIHRoZW4gd2UgYXJlIGRvbmVcbiAgICBpZiAobWF0Y2hbMF0gPT09ICcrJykge1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgY29udGV4dENoYW5nZXMgPSBjb250ZXh0Q2hhbmdlcyB8fCBjaGFuZ2VbMF0gIT09ICcgJztcblxuICAgIG1lcmdlZC5wdXNoKG1hdGNoKTtcbiAgICBtYXRjaEluZGV4Kys7XG5cbiAgICAvLyBDb25zdW1lIGFueSBhZGRpdGlvbnMgaW4gdGhlIG90aGVyIGJsb2NrIGFzIGEgY29uZmxpY3QgdG8gYXR0ZW1wdFxuICAgIC8vIHRvIHB1bGwgaW4gdGhlIHJlbWFpbmluZyBjb250ZXh0IGFmdGVyIHRoaXNcbiAgICBpZiAoY2hhbmdlWzBdID09PSAnKycpIHtcbiAgICAgIGNvbmZsaWN0ZWQgPSB0cnVlO1xuXG4gICAgICB3aGlsZSAoY2hhbmdlWzBdID09PSAnKycpIHtcbiAgICAgICAgY2hhbmdlcy5wdXNoKGNoYW5nZSk7XG4gICAgICAgIGNoYW5nZSA9IHN0YXRlLmxpbmVzWysrc3RhdGUuaW5kZXhdO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChtYXRjaC5zdWJzdHIoMSkgPT09IGNoYW5nZS5zdWJzdHIoMSkpIHtcbiAgICAgIGNoYW5nZXMucHVzaChjaGFuZ2UpO1xuICAgICAgc3RhdGUuaW5kZXgrKztcbiAgICB9IGVsc2Uge1xuICAgICAgY29uZmxpY3RlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKChtYXRjaENoYW5nZXNbbWF0Y2hJbmRleF0gfHwgJycpWzBdID09PSAnKydcbiAgICAgICYmIGNvbnRleHRDaGFuZ2VzKSB7XG4gICAgY29uZmxpY3RlZCA9IHRydWU7XG4gIH1cblxuICBpZiAoY29uZmxpY3RlZCkge1xuICAgIHJldHVybiBjaGFuZ2VzO1xuICB9XG5cbiAgd2hpbGUgKG1hdGNoSW5kZXggPCBtYXRjaENoYW5nZXMubGVuZ3RoKSB7XG4gICAgbWVyZ2VkLnB1c2gobWF0Y2hDaGFuZ2VzW21hdGNoSW5kZXgrK10pO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBtZXJnZWQsXG4gICAgY2hhbmdlc1xuICB9O1xufVxuXG5mdW5jdGlvbiBhbGxSZW1vdmVzKGNoYW5nZXMpIHtcbiAgcmV0dXJuIGNoYW5nZXMucmVkdWNlKGZ1bmN0aW9uKHByZXYsIGNoYW5nZSkge1xuICAgIHJldHVybiBwcmV2ICYmIGNoYW5nZVswXSA9PT0gJy0nO1xuICB9LCB0cnVlKTtcbn1cbmZ1bmN0aW9uIHNraXBSZW1vdmVTdXBlcnNldChzdGF0ZSwgcmVtb3ZlQ2hhbmdlcywgZGVsdGEpIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBkZWx0YTsgaSsrKSB7XG4gICAgbGV0IGNoYW5nZUNvbnRlbnQgPSByZW1vdmVDaGFuZ2VzW3JlbW92ZUNoYW5nZXMubGVuZ3RoIC0gZGVsdGEgKyBpXS5zdWJzdHIoMSk7XG4gICAgaWYgKHN0YXRlLmxpbmVzW3N0YXRlLmluZGV4ICsgaV0gIT09ICcgJyArIGNoYW5nZUNvbnRlbnQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBzdGF0ZS5pbmRleCArPSBkZWx0YTtcbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGNhbGNPbGROZXdMaW5lQ291bnQobGluZXMpIHtcbiAgbGV0IG9sZExpbmVzID0gMDtcbiAgbGV0IG5ld0xpbmVzID0gMDtcblxuICBsaW5lcy5mb3JFYWNoKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICBpZiAodHlwZW9mIGxpbmUgIT09ICdzdHJpbmcnKSB7XG4gICAgICBsZXQgbXlDb3VudCA9IGNhbGNPbGROZXdMaW5lQ291bnQobGluZS5taW5lKTtcbiAgICAgIGxldCB0aGVpckNvdW50ID0gY2FsY09sZE5ld0xpbmVDb3VudChsaW5lLnRoZWlycyk7XG5cbiAgICAgIGlmIChvbGRMaW5lcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmIChteUNvdW50Lm9sZExpbmVzID09PSB0aGVpckNvdW50Lm9sZExpbmVzKSB7XG4gICAgICAgICAgb2xkTGluZXMgKz0gbXlDb3VudC5vbGRMaW5lcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvbGRMaW5lcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAobmV3TGluZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAobXlDb3VudC5uZXdMaW5lcyA9PT0gdGhlaXJDb3VudC5uZXdMaW5lcykge1xuICAgICAgICAgIG5ld0xpbmVzICs9IG15Q291bnQubmV3TGluZXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbmV3TGluZXMgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKG5ld0xpbmVzICE9PSB1bmRlZmluZWQgJiYgKGxpbmVbMF0gPT09ICcrJyB8fCBsaW5lWzBdID09PSAnICcpKSB7XG4gICAgICAgIG5ld0xpbmVzKys7XG4gICAgICB9XG4gICAgICBpZiAob2xkTGluZXMgIT09IHVuZGVmaW5lZCAmJiAobGluZVswXSA9PT0gJy0nIHx8IGxpbmVbMF0gPT09ICcgJykpIHtcbiAgICAgICAgb2xkTGluZXMrKztcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiB7b2xkTGluZXMsIG5ld0xpbmVzfTtcbn1cbiJdfQ==
diff --git a/node_modules/libtap/node_modules/diff/lib/patch/parse.js b/node_modules/libtap/node_modules/diff/lib/patch/parse.js
new file mode 100644
index 0000000000000..b65d5c6fb4139
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/patch/parse.js
@@ -0,0 +1,156 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.parsePatch = parsePatch;
+
+/*istanbul ignore end*/
+function parsePatch(uniDiff) {
+  /*istanbul ignore start*/
+  var
+  /*istanbul ignore end*/
+  options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+  var diffstr = uniDiff.split(/\r\n|[\n\v\f\r\x85]/),
+      delimiters = uniDiff.match(/\r\n|[\n\v\f\r\x85]/g) || [],
+      list = [],
+      i = 0;
+
+  function parseIndex() {
+    var index = {};
+    list.push(index); // Parse diff metadata
+
+    while (i < diffstr.length) {
+      var line = diffstr[i]; // File header found, end parsing diff metadata
+
+      if (/^(\-\-\-|\+\+\+|@@)\s/.test(line)) {
+        break;
+      } // Diff index
+
+
+      var header = /^(?:Index:|diff(?: -r \w+)+)\s+(.+?)\s*$/.exec(line);
+
+      if (header) {
+        index.index = header[1];
+      }
+
+      i++;
+    } // Parse file headers if they are defined. Unified diff requires them, but
+    // there's no technical issues to have an isolated hunk without file header
+
+
+    parseFileHeader(index);
+    parseFileHeader(index); // Parse hunks
+
+    index.hunks = [];
+
+    while (i < diffstr.length) {
+      var _line = diffstr[i];
+
+      if (/^(Index:|diff|\-\-\-|\+\+\+)\s/.test(_line)) {
+        break;
+      } else if (/^@@/.test(_line)) {
+        index.hunks.push(parseHunk());
+      } else if (_line && options.strict) {
+        // Ignore unexpected content unless in strict mode
+        throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(_line));
+      } else {
+        i++;
+      }
+    }
+  } // Parses the --- and +++ headers, if none are found, no lines
+  // are consumed.
+
+
+  function parseFileHeader(index) {
+    var fileHeader = /^(---|\+\+\+)\s+(.*)$/.exec(diffstr[i]);
+
+    if (fileHeader) {
+      var keyPrefix = fileHeader[1] === '---' ? 'old' : 'new';
+      var data = fileHeader[2].split('\t', 2);
+      var fileName = data[0].replace(/\\\\/g, '\\');
+
+      if (/^".*"$/.test(fileName)) {
+        fileName = fileName.substr(1, fileName.length - 2);
+      }
+
+      index[keyPrefix + 'FileName'] = fileName;
+      index[keyPrefix + 'Header'] = (data[1] || '').trim();
+      i++;
+    }
+  } // Parses a hunk
+  // This assumes that we are at the start of a hunk.
+
+
+  function parseHunk() {
+    var chunkHeaderIndex = i,
+        chunkHeaderLine = diffstr[i++],
+        chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
+    var hunk = {
+      oldStart: +chunkHeader[1],
+      oldLines: +chunkHeader[2] || 1,
+      newStart: +chunkHeader[3],
+      newLines: +chunkHeader[4] || 1,
+      lines: [],
+      linedelimiters: []
+    };
+    var addCount = 0,
+        removeCount = 0;
+
+    for (; i < diffstr.length; i++) {
+      // Lines starting with '---' could be mistaken for the "remove line" operation
+      // But they could be the header for the next file. Therefore prune such cases out.
+      if (diffstr[i].indexOf('--- ') === 0 && i + 2 < diffstr.length && diffstr[i + 1].indexOf('+++ ') === 0 && diffstr[i + 2].indexOf('@@') === 0) {
+        break;
+      }
+
+      var operation = diffstr[i].length == 0 && i != diffstr.length - 1 ? ' ' : diffstr[i][0];
+
+      if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') {
+        hunk.lines.push(diffstr[i]);
+        hunk.linedelimiters.push(delimiters[i] || '\n');
+
+        if (operation === '+') {
+          addCount++;
+        } else if (operation === '-') {
+          removeCount++;
+        } else if (operation === ' ') {
+          addCount++;
+          removeCount++;
+        }
+      } else {
+        break;
+      }
+    } // Handle the empty block count case
+
+
+    if (!addCount && hunk.newLines === 1) {
+      hunk.newLines = 0;
+    }
+
+    if (!removeCount && hunk.oldLines === 1) {
+      hunk.oldLines = 0;
+    } // Perform optional sanity checking
+
+
+    if (options.strict) {
+      if (addCount !== hunk.newLines) {
+        throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
+      }
+
+      if (removeCount !== hunk.oldLines) {
+        throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
+      }
+    }
+
+    return hunk;
+  }
+
+  while (i < diffstr.length) {
+    parseIndex();
+  }
+
+  return list;
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYXRjaC9wYXJzZS5qcyJdLCJuYW1lcyI6WyJwYXJzZVBhdGNoIiwidW5pRGlmZiIsIm9wdGlvbnMiLCJkaWZmc3RyIiwic3BsaXQiLCJkZWxpbWl0ZXJzIiwibWF0Y2giLCJsaXN0IiwiaSIsInBhcnNlSW5kZXgiLCJpbmRleCIsInB1c2giLCJsZW5ndGgiLCJsaW5lIiwidGVzdCIsImhlYWRlciIsImV4ZWMiLCJwYXJzZUZpbGVIZWFkZXIiLCJodW5rcyIsInBhcnNlSHVuayIsInN0cmljdCIsIkVycm9yIiwiSlNPTiIsInN0cmluZ2lmeSIsImZpbGVIZWFkZXIiLCJrZXlQcmVmaXgiLCJkYXRhIiwiZmlsZU5hbWUiLCJyZXBsYWNlIiwic3Vic3RyIiwidHJpbSIsImNodW5rSGVhZGVySW5kZXgiLCJjaHVua0hlYWRlckxpbmUiLCJjaHVua0hlYWRlciIsImh1bmsiLCJvbGRTdGFydCIsIm9sZExpbmVzIiwibmV3U3RhcnQiLCJuZXdMaW5lcyIsImxpbmVzIiwibGluZWRlbGltaXRlcnMiLCJhZGRDb3VudCIsInJlbW92ZUNvdW50IiwiaW5kZXhPZiIsIm9wZXJhdGlvbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQU8sU0FBU0EsVUFBVCxDQUFvQkMsT0FBcEIsRUFBMkM7QUFBQTtBQUFBO0FBQUE7QUFBZEMsRUFBQUEsT0FBYyx1RUFBSixFQUFJO0FBQ2hELE1BQUlDLE9BQU8sR0FBR0YsT0FBTyxDQUFDRyxLQUFSLENBQWMscUJBQWQsQ0FBZDtBQUFBLE1BQ0lDLFVBQVUsR0FBR0osT0FBTyxDQUFDSyxLQUFSLENBQWMsc0JBQWQsS0FBeUMsRUFEMUQ7QUFBQSxNQUVJQyxJQUFJLEdBQUcsRUFGWDtBQUFBLE1BR0lDLENBQUMsR0FBRyxDQUhSOztBQUtBLFdBQVNDLFVBQVQsR0FBc0I7QUFDcEIsUUFBSUMsS0FBSyxHQUFHLEVBQVo7QUFDQUgsSUFBQUEsSUFBSSxDQUFDSSxJQUFMLENBQVVELEtBQVYsRUFGb0IsQ0FJcEI7O0FBQ0EsV0FBT0YsQ0FBQyxHQUFHTCxPQUFPLENBQUNTLE1BQW5CLEVBQTJCO0FBQ3pCLFVBQUlDLElBQUksR0FBR1YsT0FBTyxDQUFDSyxDQUFELENBQWxCLENBRHlCLENBR3pCOztBQUNBLFVBQUssdUJBQUQsQ0FBMEJNLElBQTFCLENBQStCRCxJQUEvQixDQUFKLEVBQTBDO0FBQ3hDO0FBQ0QsT0FOd0IsQ0FRekI7OztBQUNBLFVBQUlFLE1BQU0sR0FBSSwwQ0FBRCxDQUE2Q0MsSUFBN0MsQ0FBa0RILElBQWxELENBQWI7O0FBQ0EsVUFBSUUsTUFBSixFQUFZO0FBQ1ZMLFFBQUFBLEtBQUssQ0FBQ0EsS0FBTixHQUFjSyxNQUFNLENBQUMsQ0FBRCxDQUFwQjtBQUNEOztBQUVEUCxNQUFBQSxDQUFDO0FBQ0YsS0FwQm1CLENBc0JwQjtBQUNBOzs7QUFDQVMsSUFBQUEsZUFBZSxDQUFDUCxLQUFELENBQWY7QUFDQU8sSUFBQUEsZUFBZSxDQUFDUCxLQUFELENBQWYsQ0F6Qm9CLENBMkJwQjs7QUFDQUEsSUFBQUEsS0FBSyxDQUFDUSxLQUFOLEdBQWMsRUFBZDs7QUFFQSxXQUFPVixDQUFDLEdBQUdMLE9BQU8sQ0FBQ1MsTUFBbkIsRUFBMkI7QUFDekIsVUFBSUMsS0FBSSxHQUFHVixPQUFPLENBQUNLLENBQUQsQ0FBbEI7O0FBRUEsVUFBSyxnQ0FBRCxDQUFtQ00sSUFBbkMsQ0FBd0NELEtBQXhDLENBQUosRUFBbUQ7QUFDakQ7QUFDRCxPQUZELE1BRU8sSUFBSyxLQUFELENBQVFDLElBQVIsQ0FBYUQsS0FBYixDQUFKLEVBQXdCO0FBQzdCSCxRQUFBQSxLQUFLLENBQUNRLEtBQU4sQ0FBWVAsSUFBWixDQUFpQlEsU0FBUyxFQUExQjtBQUNELE9BRk0sTUFFQSxJQUFJTixLQUFJLElBQUlYLE9BQU8sQ0FBQ2tCLE1BQXBCLEVBQTRCO0FBQ2pDO0FBQ0EsY0FBTSxJQUFJQyxLQUFKLENBQVUsbUJBQW1CYixDQUFDLEdBQUcsQ0FBdkIsSUFBNEIsR0FBNUIsR0FBa0NjLElBQUksQ0FBQ0MsU0FBTCxDQUFlVixLQUFmLENBQTVDLENBQU47QUFDRCxPQUhNLE1BR0E7QUFDTEwsUUFBQUEsQ0FBQztBQUNGO0FBQ0Y7QUFDRixHQWxEK0MsQ0FvRGhEO0FBQ0E7OztBQUNBLFdBQVNTLGVBQVQsQ0FBeUJQLEtBQXpCLEVBQWdDO0FBQzlCLFFBQU1jLFVBQVUsR0FBSSx1QkFBRCxDQUEwQlIsSUFBMUIsQ0FBK0JiLE9BQU8sQ0FBQ0ssQ0FBRCxDQUF0QyxDQUFuQjs7QUFDQSxRQUFJZ0IsVUFBSixFQUFnQjtBQUNkLFVBQUlDLFNBQVMsR0FBR0QsVUFBVSxDQUFDLENBQUQsQ0FBVixLQUFrQixLQUFsQixHQUEwQixLQUExQixHQUFrQyxLQUFsRDtBQUNBLFVBQU1FLElBQUksR0FBR0YsVUFBVSxDQUFDLENBQUQsQ0FBVixDQUFjcEIsS0FBZCxDQUFvQixJQUFwQixFQUEwQixDQUExQixDQUFiO0FBQ0EsVUFBSXVCLFFBQVEsR0FBR0QsSUFBSSxDQUFDLENBQUQsQ0FBSixDQUFRRSxPQUFSLENBQWdCLE9BQWhCLEVBQXlCLElBQXpCLENBQWY7O0FBQ0EsVUFBSyxRQUFELENBQVdkLElBQVgsQ0FBZ0JhLFFBQWhCLENBQUosRUFBK0I7QUFDN0JBLFFBQUFBLFFBQVEsR0FBR0EsUUFBUSxDQUFDRSxNQUFULENBQWdCLENBQWhCLEVBQW1CRixRQUFRLENBQUNmLE1BQVQsR0FBa0IsQ0FBckMsQ0FBWDtBQUNEOztBQUNERixNQUFBQSxLQUFLLENBQUNlLFNBQVMsR0FBRyxVQUFiLENBQUwsR0FBZ0NFLFFBQWhDO0FBQ0FqQixNQUFBQSxLQUFLLENBQUNlLFNBQVMsR0FBRyxRQUFiLENBQUwsR0FBOEIsQ0FBQ0MsSUFBSSxDQUFDLENBQUQsQ0FBSixJQUFXLEVBQVosRUFBZ0JJLElBQWhCLEVBQTlCO0FBRUF0QixNQUFBQSxDQUFDO0FBQ0Y7QUFDRixHQXBFK0MsQ0FzRWhEO0FBQ0E7OztBQUNBLFdBQVNXLFNBQVQsR0FBcUI7QUFDbkIsUUFBSVksZ0JBQWdCLEdBQUd2QixDQUF2QjtBQUFBLFFBQ0l3QixlQUFlLEdBQUc3QixPQUFPLENBQUNLLENBQUMsRUFBRixDQUQ3QjtBQUFBLFFBRUl5QixXQUFXLEdBQUdELGVBQWUsQ0FBQzVCLEtBQWhCLENBQXNCLDRDQUF0QixDQUZsQjtBQUlBLFFBQUk4QixJQUFJLEdBQUc7QUFDVEMsTUFBQUEsUUFBUSxFQUFFLENBQUNGLFdBQVcsQ0FBQyxDQUFELENBRGI7QUFFVEcsTUFBQUEsUUFBUSxFQUFFLENBQUNILFdBQVcsQ0FBQyxDQUFELENBQVosSUFBbUIsQ0FGcEI7QUFHVEksTUFBQUEsUUFBUSxFQUFFLENBQUNKLFdBQVcsQ0FBQyxDQUFELENBSGI7QUFJVEssTUFBQUEsUUFBUSxFQUFFLENBQUNMLFdBQVcsQ0FBQyxDQUFELENBQVosSUFBbUIsQ0FKcEI7QUFLVE0sTUFBQUEsS0FBSyxFQUFFLEVBTEU7QUFNVEMsTUFBQUEsY0FBYyxFQUFFO0FBTlAsS0FBWDtBQVNBLFFBQUlDLFFBQVEsR0FBRyxDQUFmO0FBQUEsUUFDSUMsV0FBVyxHQUFHLENBRGxCOztBQUVBLFdBQU9sQyxDQUFDLEdBQUdMLE9BQU8sQ0FBQ1MsTUFBbkIsRUFBMkJKLENBQUMsRUFBNUIsRUFBZ0M7QUFDOUI7QUFDQTtBQUNBLFVBQUlMLE9BQU8sQ0FBQ0ssQ0FBRCxDQUFQLENBQVdtQyxPQUFYLENBQW1CLE1BQW5CLE1BQStCLENBQS9CLElBQ01uQyxDQUFDLEdBQUcsQ0FBSixHQUFRTCxPQUFPLENBQUNTLE1BRHRCLElBRUtULE9BQU8sQ0FBQ0ssQ0FBQyxHQUFHLENBQUwsQ0FBUCxDQUFlbUMsT0FBZixDQUF1QixNQUF2QixNQUFtQyxDQUZ4QyxJQUdLeEMsT0FBTyxDQUFDSyxDQUFDLEdBQUcsQ0FBTCxDQUFQLENBQWVtQyxPQUFmLENBQXVCLElBQXZCLE1BQWlDLENBSDFDLEVBRzZDO0FBQ3pDO0FBQ0g7O0FBQ0QsVUFBSUMsU0FBUyxHQUFJekMsT0FBTyxDQUFDSyxDQUFELENBQVAsQ0FBV0ksTUFBWCxJQUFxQixDQUFyQixJQUEwQkosQ0FBQyxJQUFLTCxPQUFPLENBQUNTLE1BQVIsR0FBaUIsQ0FBbEQsR0FBd0QsR0FBeEQsR0FBOERULE9BQU8sQ0FBQ0ssQ0FBRCxDQUFQLENBQVcsQ0FBWCxDQUE5RTs7QUFFQSxVQUFJb0MsU0FBUyxLQUFLLEdBQWQsSUFBcUJBLFNBQVMsS0FBSyxHQUFuQyxJQUEwQ0EsU0FBUyxLQUFLLEdBQXhELElBQStEQSxTQUFTLEtBQUssSUFBakYsRUFBdUY7QUFDckZWLFFBQUFBLElBQUksQ0FBQ0ssS0FBTCxDQUFXNUIsSUFBWCxDQUFnQlIsT0FBTyxDQUFDSyxDQUFELENBQXZCO0FBQ0EwQixRQUFBQSxJQUFJLENBQUNNLGNBQUwsQ0FBb0I3QixJQUFwQixDQUF5Qk4sVUFBVSxDQUFDRyxDQUFELENBQVYsSUFBaUIsSUFBMUM7O0FBRUEsWUFBSW9DLFNBQVMsS0FBSyxHQUFsQixFQUF1QjtBQUNyQkgsVUFBQUEsUUFBUTtBQUNULFNBRkQsTUFFTyxJQUFJRyxTQUFTLEtBQUssR0FBbEIsRUFBdUI7QUFDNUJGLFVBQUFBLFdBQVc7QUFDWixTQUZNLE1BRUEsSUFBSUUsU0FBUyxLQUFLLEdBQWxCLEVBQXVCO0FBQzVCSCxVQUFBQSxRQUFRO0FBQ1JDLFVBQUFBLFdBQVc7QUFDWjtBQUNGLE9BWkQsTUFZTztBQUNMO0FBQ0Q7QUFDRixLQTFDa0IsQ0E0Q25COzs7QUFDQSxRQUFJLENBQUNELFFBQUQsSUFBYVAsSUFBSSxDQUFDSSxRQUFMLEtBQWtCLENBQW5DLEVBQXNDO0FBQ3BDSixNQUFBQSxJQUFJLENBQUNJLFFBQUwsR0FBZ0IsQ0FBaEI7QUFDRDs7QUFDRCxRQUFJLENBQUNJLFdBQUQsSUFBZ0JSLElBQUksQ0FBQ0UsUUFBTCxLQUFrQixDQUF0QyxFQUF5QztBQUN2Q0YsTUFBQUEsSUFBSSxDQUFDRSxRQUFMLEdBQWdCLENBQWhCO0FBQ0QsS0FsRGtCLENBb0RuQjs7O0FBQ0EsUUFBSWxDLE9BQU8sQ0FBQ2tCLE1BQVosRUFBb0I7QUFDbEIsVUFBSXFCLFFBQVEsS0FBS1AsSUFBSSxDQUFDSSxRQUF0QixFQUFnQztBQUM5QixjQUFNLElBQUlqQixLQUFKLENBQVUsc0RBQXNEVSxnQkFBZ0IsR0FBRyxDQUF6RSxDQUFWLENBQU47QUFDRDs7QUFDRCxVQUFJVyxXQUFXLEtBQUtSLElBQUksQ0FBQ0UsUUFBekIsRUFBbUM7QUFDakMsY0FBTSxJQUFJZixLQUFKLENBQVUsd0RBQXdEVSxnQkFBZ0IsR0FBRyxDQUEzRSxDQUFWLENBQU47QUFDRDtBQUNGOztBQUVELFdBQU9HLElBQVA7QUFDRDs7QUFFRCxTQUFPMUIsQ0FBQyxHQUFHTCxPQUFPLENBQUNTLE1BQW5CLEVBQTJCO0FBQ3pCSCxJQUFBQSxVQUFVO0FBQ1g7O0FBRUQsU0FBT0YsSUFBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGZ1bmN0aW9uIHBhcnNlUGF0Y2godW5pRGlmZiwgb3B0aW9ucyA9IHt9KSB7XG4gIGxldCBkaWZmc3RyID0gdW5pRGlmZi5zcGxpdCgvXFxyXFxufFtcXG5cXHZcXGZcXHJcXHg4NV0vKSxcbiAgICAgIGRlbGltaXRlcnMgPSB1bmlEaWZmLm1hdGNoKC9cXHJcXG58W1xcblxcdlxcZlxcclxceDg1XS9nKSB8fCBbXSxcbiAgICAgIGxpc3QgPSBbXSxcbiAgICAgIGkgPSAwO1xuXG4gIGZ1bmN0aW9uIHBhcnNlSW5kZXgoKSB7XG4gICAgbGV0IGluZGV4ID0ge307XG4gICAgbGlzdC5wdXNoKGluZGV4KTtcblxuICAgIC8vIFBhcnNlIGRpZmYgbWV0YWRhdGFcbiAgICB3aGlsZSAoaSA8IGRpZmZzdHIubGVuZ3RoKSB7XG4gICAgICBsZXQgbGluZSA9IGRpZmZzdHJbaV07XG5cbiAgICAgIC8vIEZpbGUgaGVhZGVyIGZvdW5kLCBlbmQgcGFyc2luZyBkaWZmIG1ldGFkYXRhXG4gICAgICBpZiAoKC9eKFxcLVxcLVxcLXxcXCtcXCtcXCt8QEApXFxzLykudGVzdChsaW5lKSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgLy8gRGlmZiBpbmRleFxuICAgICAgbGV0IGhlYWRlciA9ICgvXig/OkluZGV4OnxkaWZmKD86IC1yIFxcdyspKylcXHMrKC4rPylcXHMqJC8pLmV4ZWMobGluZSk7XG4gICAgICBpZiAoaGVhZGVyKSB7XG4gICAgICAgIGluZGV4LmluZGV4ID0gaGVhZGVyWzFdO1xuICAgICAgfVxuXG4gICAgICBpKys7XG4gICAgfVxuXG4gICAgLy8gUGFyc2UgZmlsZSBoZWFkZXJzIGlmIHRoZXkgYXJlIGRlZmluZWQuIFVuaWZpZWQgZGlmZiByZXF1aXJlcyB0aGVtLCBidXRcbiAgICAvLyB0aGVyZSdzIG5vIHRlY2huaWNhbCBpc3N1ZXMgdG8gaGF2ZSBhbiBpc29sYXRlZCBodW5rIHdpdGhvdXQgZmlsZSBoZWFkZXJcbiAgICBwYXJzZUZpbGVIZWFkZXIoaW5kZXgpO1xuICAgIHBhcnNlRmlsZUhlYWRlcihpbmRleCk7XG5cbiAgICAvLyBQYXJzZSBodW5rc1xuICAgIGluZGV4Lmh1bmtzID0gW107XG5cbiAgICB3aGlsZSAoaSA8IGRpZmZzdHIubGVuZ3RoKSB7XG4gICAgICBsZXQgbGluZSA9IGRpZmZzdHJbaV07XG5cbiAgICAgIGlmICgoL14oSW5kZXg6fGRpZmZ8XFwtXFwtXFwtfFxcK1xcK1xcKylcXHMvKS50ZXN0KGxpbmUpKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfSBlbHNlIGlmICgoL15AQC8pLnRlc3QobGluZSkpIHtcbiAgICAgICAgaW5kZXguaHVua3MucHVzaChwYXJzZUh1bmsoKSk7XG4gICAgICB9IGVsc2UgaWYgKGxpbmUgJiYgb3B0aW9ucy5zdHJpY3QpIHtcbiAgICAgICAgLy8gSWdub3JlIHVuZXhwZWN0ZWQgY29udGVudCB1bmxlc3MgaW4gc3RyaWN0IG1vZGVcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIGxpbmUgJyArIChpICsgMSkgKyAnICcgKyBKU09OLnN0cmluZ2lmeShsaW5lKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpKys7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gUGFyc2VzIHRoZSAtLS0gYW5kICsrKyBoZWFkZXJzLCBpZiBub25lIGFyZSBmb3VuZCwgbm8gbGluZXNcbiAgLy8gYXJlIGNvbnN1bWVkLlxuICBmdW5jdGlvbiBwYXJzZUZpbGVIZWFkZXIoaW5kZXgpIHtcbiAgICBjb25zdCBmaWxlSGVhZGVyID0gKC9eKC0tLXxcXCtcXCtcXCspXFxzKyguKikkLykuZXhlYyhkaWZmc3RyW2ldKTtcbiAgICBpZiAoZmlsZUhlYWRlcikge1xuICAgICAgbGV0IGtleVByZWZpeCA9IGZpbGVIZWFkZXJbMV0gPT09ICctLS0nID8gJ29sZCcgOiAnbmV3JztcbiAgICAgIGNvbnN0IGRhdGEgPSBmaWxlSGVhZGVyWzJdLnNwbGl0KCdcXHQnLCAyKTtcbiAgICAgIGxldCBmaWxlTmFtZSA9IGRhdGFbMF0ucmVwbGFjZSgvXFxcXFxcXFwvZywgJ1xcXFwnKTtcbiAgICAgIGlmICgoL15cIi4qXCIkLykudGVzdChmaWxlTmFtZSkpIHtcbiAgICAgICAgZmlsZU5hbWUgPSBmaWxlTmFtZS5zdWJzdHIoMSwgZmlsZU5hbWUubGVuZ3RoIC0gMik7XG4gICAgICB9XG4gICAgICBpbmRleFtrZXlQcmVmaXggKyAnRmlsZU5hbWUnXSA9IGZpbGVOYW1lO1xuICAgICAgaW5kZXhba2V5UHJlZml4ICsgJ0hlYWRlciddID0gKGRhdGFbMV0gfHwgJycpLnRyaW0oKTtcblxuICAgICAgaSsrO1xuICAgIH1cbiAgfVxuXG4gIC8vIFBhcnNlcyBhIGh1bmtcbiAgLy8gVGhpcyBhc3N1bWVzIHRoYXQgd2UgYXJlIGF0IHRoZSBzdGFydCBvZiBhIGh1bmsuXG4gIGZ1bmN0aW9uIHBhcnNlSHVuaygpIHtcbiAgICBsZXQgY2h1bmtIZWFkZXJJbmRleCA9IGksXG4gICAgICAgIGNodW5rSGVhZGVyTGluZSA9IGRpZmZzdHJbaSsrXSxcbiAgICAgICAgY2h1bmtIZWFkZXIgPSBjaHVua0hlYWRlckxpbmUuc3BsaXQoL0BAIC0oXFxkKykoPzosKFxcZCspKT8gXFwrKFxcZCspKD86LChcXGQrKSk/IEBALyk7XG5cbiAgICBsZXQgaHVuayA9IHtcbiAgICAgIG9sZFN0YXJ0OiArY2h1bmtIZWFkZXJbMV0sXG4gICAgICBvbGRMaW5lczogK2NodW5rSGVhZGVyWzJdIHx8IDEsXG4gICAgICBuZXdTdGFydDogK2NodW5rSGVhZGVyWzNdLFxuICAgICAgbmV3TGluZXM6ICtjaHVua0hlYWRlcls0XSB8fCAxLFxuICAgICAgbGluZXM6IFtdLFxuICAgICAgbGluZWRlbGltaXRlcnM6IFtdXG4gICAgfTtcblxuICAgIGxldCBhZGRDb3VudCA9IDAsXG4gICAgICAgIHJlbW92ZUNvdW50ID0gMDtcbiAgICBmb3IgKDsgaSA8IGRpZmZzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIC8vIExpbmVzIHN0YXJ0aW5nIHdpdGggJy0tLScgY291bGQgYmUgbWlzdGFrZW4gZm9yIHRoZSBcInJlbW92ZSBsaW5lXCIgb3BlcmF0aW9uXG4gICAgICAvLyBCdXQgdGhleSBjb3VsZCBiZSB0aGUgaGVhZGVyIGZvciB0aGUgbmV4dCBmaWxlLiBUaGVyZWZvcmUgcHJ1bmUgc3VjaCBjYXNlcyBvdXQuXG4gICAgICBpZiAoZGlmZnN0cltpXS5pbmRleE9mKCctLS0gJykgPT09IDBcbiAgICAgICAgICAgICYmIChpICsgMiA8IGRpZmZzdHIubGVuZ3RoKVxuICAgICAgICAgICAgJiYgZGlmZnN0cltpICsgMV0uaW5kZXhPZignKysrICcpID09PSAwXG4gICAgICAgICAgICAmJiBkaWZmc3RyW2kgKyAyXS5pbmRleE9mKCdAQCcpID09PSAwKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBsZXQgb3BlcmF0aW9uID0gKGRpZmZzdHJbaV0ubGVuZ3RoID09IDAgJiYgaSAhPSAoZGlmZnN0ci5sZW5ndGggLSAxKSkgPyAnICcgOiBkaWZmc3RyW2ldWzBdO1xuXG4gICAgICBpZiAob3BlcmF0aW9uID09PSAnKycgfHwgb3BlcmF0aW9uID09PSAnLScgfHwgb3BlcmF0aW9uID09PSAnICcgfHwgb3BlcmF0aW9uID09PSAnXFxcXCcpIHtcbiAgICAgICAgaHVuay5saW5lcy5wdXNoKGRpZmZzdHJbaV0pO1xuICAgICAgICBodW5rLmxpbmVkZWxpbWl0ZXJzLnB1c2goZGVsaW1pdGVyc1tpXSB8fCAnXFxuJyk7XG5cbiAgICAgICAgaWYgKG9wZXJhdGlvbiA9PT0gJysnKSB7XG4gICAgICAgICAgYWRkQ291bnQrKztcbiAgICAgICAgfSBlbHNlIGlmIChvcGVyYXRpb24gPT09ICctJykge1xuICAgICAgICAgIHJlbW92ZUNvdW50Kys7XG4gICAgICAgIH0gZWxzZSBpZiAob3BlcmF0aW9uID09PSAnICcpIHtcbiAgICAgICAgICBhZGRDb3VudCsrO1xuICAgICAgICAgIHJlbW92ZUNvdW50Kys7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEhhbmRsZSB0aGUgZW1wdHkgYmxvY2sgY291bnQgY2FzZVxuICAgIGlmICghYWRkQ291bnQgJiYgaHVuay5uZXdMaW5lcyA9PT0gMSkge1xuICAgICAgaHVuay5uZXdMaW5lcyA9IDA7XG4gICAgfVxuICAgIGlmICghcmVtb3ZlQ291bnQgJiYgaHVuay5vbGRMaW5lcyA9PT0gMSkge1xuICAgICAgaHVuay5vbGRMaW5lcyA9IDA7XG4gICAgfVxuXG4gICAgLy8gUGVyZm9ybSBvcHRpb25hbCBzYW5pdHkgY2hlY2tpbmdcbiAgICBpZiAob3B0aW9ucy5zdHJpY3QpIHtcbiAgICAgIGlmIChhZGRDb3VudCAhPT0gaHVuay5uZXdMaW5lcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FkZGVkIGxpbmUgY291bnQgZGlkIG5vdCBtYXRjaCBmb3IgaHVuayBhdCBsaW5lICcgKyAoY2h1bmtIZWFkZXJJbmRleCArIDEpKTtcbiAgICAgIH1cbiAgICAgIGlmIChyZW1vdmVDb3VudCAhPT0gaHVuay5vbGRMaW5lcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlbW92ZWQgbGluZSBjb3VudCBkaWQgbm90IG1hdGNoIGZvciBodW5rIGF0IGxpbmUgJyArIChjaHVua0hlYWRlckluZGV4ICsgMSkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBodW5rO1xuICB9XG5cbiAgd2hpbGUgKGkgPCBkaWZmc3RyLmxlbmd0aCkge1xuICAgIHBhcnNlSW5kZXgoKTtcbiAgfVxuXG4gIHJldHVybiBsaXN0O1xufVxuIl19
diff --git a/node_modules/libtap/node_modules/diff/lib/util/array.js b/node_modules/libtap/node_modules/diff/lib/util/array.js
new file mode 100644
index 0000000000000..aecf67ac817c1
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/util/array.js
@@ -0,0 +1,32 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.arrayEqual = arrayEqual;
+exports.arrayStartsWith = arrayStartsWith;
+
+/*istanbul ignore end*/
+function arrayEqual(a, b) {
+  if (a.length !== b.length) {
+    return false;
+  }
+
+  return arrayStartsWith(a, b);
+}
+
+function arrayStartsWith(array, start) {
+  if (start.length > array.length) {
+    return false;
+  }
+
+  for (var i = 0; i < start.length; i++) {
+    if (start[i] !== array[i]) {
+      return false;
+    }
+  }
+
+  return true;
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsL2FycmF5LmpzIl0sIm5hbWVzIjpbImFycmF5RXF1YWwiLCJhIiwiYiIsImxlbmd0aCIsImFycmF5U3RhcnRzV2l0aCIsImFycmF5Iiwic3RhcnQiLCJpIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQU8sU0FBU0EsVUFBVCxDQUFvQkMsQ0FBcEIsRUFBdUJDLENBQXZCLEVBQTBCO0FBQy9CLE1BQUlELENBQUMsQ0FBQ0UsTUFBRixLQUFhRCxDQUFDLENBQUNDLE1BQW5CLEVBQTJCO0FBQ3pCLFdBQU8sS0FBUDtBQUNEOztBQUVELFNBQU9DLGVBQWUsQ0FBQ0gsQ0FBRCxFQUFJQyxDQUFKLENBQXRCO0FBQ0Q7O0FBRU0sU0FBU0UsZUFBVCxDQUF5QkMsS0FBekIsRUFBZ0NDLEtBQWhDLEVBQXVDO0FBQzVDLE1BQUlBLEtBQUssQ0FBQ0gsTUFBTixHQUFlRSxLQUFLLENBQUNGLE1BQXpCLEVBQWlDO0FBQy9CLFdBQU8sS0FBUDtBQUNEOztBQUVELE9BQUssSUFBSUksQ0FBQyxHQUFHLENBQWIsRUFBZ0JBLENBQUMsR0FBR0QsS0FBSyxDQUFDSCxNQUExQixFQUFrQ0ksQ0FBQyxFQUFuQyxFQUF1QztBQUNyQyxRQUFJRCxLQUFLLENBQUNDLENBQUQsQ0FBTCxLQUFhRixLQUFLLENBQUNFLENBQUQsQ0FBdEIsRUFBMkI7QUFDekIsYUFBTyxLQUFQO0FBQ0Q7QUFDRjs7QUFFRCxTQUFPLElBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBmdW5jdGlvbiBhcnJheUVxdWFsKGEsIGIpIHtcbiAgaWYgKGEubGVuZ3RoICE9PSBiLmxlbmd0aCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiBhcnJheVN0YXJ0c1dpdGgoYSwgYik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcnJheVN0YXJ0c1dpdGgoYXJyYXksIHN0YXJ0KSB7XG4gIGlmIChzdGFydC5sZW5ndGggPiBhcnJheS5sZW5ndGgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHN0YXJ0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKHN0YXJ0W2ldICE9PSBhcnJheVtpXSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuIl19
diff --git a/node_modules/libtap/node_modules/diff/lib/util/distance-iterator.js b/node_modules/libtap/node_modules/diff/lib/util/distance-iterator.js
new file mode 100644
index 0000000000000..5edbaf834bcc9
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/util/distance-iterator.js
@@ -0,0 +1,57 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = _default;
+
+/*istanbul ignore end*/
+// Iterator that traverses in the range of [min, max], stepping
+// by distance from a given start position. I.e. for [0, 4], with
+// start of 2, this will iterate 2, 3, 1, 4, 0.
+function
+/*istanbul ignore start*/
+_default
+/*istanbul ignore end*/
+(start, minLine, maxLine) {
+  var wantForward = true,
+      backwardExhausted = false,
+      forwardExhausted = false,
+      localOffset = 1;
+  return function iterator() {
+    if (wantForward && !forwardExhausted) {
+      if (backwardExhausted) {
+        localOffset++;
+      } else {
+        wantForward = false;
+      } // Check if trying to fit beyond text length, and if not, check it fits
+      // after offset location (or desired location on first iteration)
+
+
+      if (start + localOffset <= maxLine) {
+        return localOffset;
+      }
+
+      forwardExhausted = true;
+    }
+
+    if (!backwardExhausted) {
+      if (!forwardExhausted) {
+        wantForward = true;
+      } // Check if trying to fit before text beginning, and if not, check it fits
+      // before offset location
+
+
+      if (minLine <= start - localOffset) {
+        return -localOffset++;
+      }
+
+      backwardExhausted = true;
+      return iterator();
+    } // We tried to fit hunk before text beginning and beyond text length, then
+    // hunk can't fit on the text. Return undefined
+
+  };
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsL2Rpc3RhbmNlLWl0ZXJhdG9yLmpzIl0sIm5hbWVzIjpbInN0YXJ0IiwibWluTGluZSIsIm1heExpbmUiLCJ3YW50Rm9yd2FyZCIsImJhY2t3YXJkRXhoYXVzdGVkIiwiZm9yd2FyZEV4aGF1c3RlZCIsImxvY2FsT2Zmc2V0IiwiaXRlcmF0b3IiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNlO0FBQUE7QUFBQTtBQUFBO0FBQUEsQ0FBU0EsS0FBVCxFQUFnQkMsT0FBaEIsRUFBeUJDLE9BQXpCLEVBQWtDO0FBQy9DLE1BQUlDLFdBQVcsR0FBRyxJQUFsQjtBQUFBLE1BQ0lDLGlCQUFpQixHQUFHLEtBRHhCO0FBQUEsTUFFSUMsZ0JBQWdCLEdBQUcsS0FGdkI7QUFBQSxNQUdJQyxXQUFXLEdBQUcsQ0FIbEI7QUFLQSxTQUFPLFNBQVNDLFFBQVQsR0FBb0I7QUFDekIsUUFBSUosV0FBVyxJQUFJLENBQUNFLGdCQUFwQixFQUFzQztBQUNwQyxVQUFJRCxpQkFBSixFQUF1QjtBQUNyQkUsUUFBQUEsV0FBVztBQUNaLE9BRkQsTUFFTztBQUNMSCxRQUFBQSxXQUFXLEdBQUcsS0FBZDtBQUNELE9BTG1DLENBT3BDO0FBQ0E7OztBQUNBLFVBQUlILEtBQUssR0FBR00sV0FBUixJQUF1QkosT0FBM0IsRUFBb0M7QUFDbEMsZUFBT0ksV0FBUDtBQUNEOztBQUVERCxNQUFBQSxnQkFBZ0IsR0FBRyxJQUFuQjtBQUNEOztBQUVELFFBQUksQ0FBQ0QsaUJBQUwsRUFBd0I7QUFDdEIsVUFBSSxDQUFDQyxnQkFBTCxFQUF1QjtBQUNyQkYsUUFBQUEsV0FBVyxHQUFHLElBQWQ7QUFDRCxPQUhxQixDQUt0QjtBQUNBOzs7QUFDQSxVQUFJRixPQUFPLElBQUlELEtBQUssR0FBR00sV0FBdkIsRUFBb0M7QUFDbEMsZUFBTyxDQUFDQSxXQUFXLEVBQW5CO0FBQ0Q7O0FBRURGLE1BQUFBLGlCQUFpQixHQUFHLElBQXBCO0FBQ0EsYUFBT0csUUFBUSxFQUFmO0FBQ0QsS0E5QndCLENBZ0N6QjtBQUNBOztBQUNELEdBbENEO0FBbUNEIiwic291cmNlc0NvbnRlbnQiOlsiLy8gSXRlcmF0b3IgdGhhdCB0cmF2ZXJzZXMgaW4gdGhlIHJhbmdlIG9mIFttaW4sIG1heF0sIHN0ZXBwaW5nXG4vLyBieSBkaXN0YW5jZSBmcm9tIGEgZ2l2ZW4gc3RhcnQgcG9zaXRpb24uIEkuZS4gZm9yIFswLCA0XSwgd2l0aFxuLy8gc3RhcnQgb2YgMiwgdGhpcyB3aWxsIGl0ZXJhdGUgMiwgMywgMSwgNCwgMC5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKHN0YXJ0LCBtaW5MaW5lLCBtYXhMaW5lKSB7XG4gIGxldCB3YW50Rm9yd2FyZCA9IHRydWUsXG4gICAgICBiYWNrd2FyZEV4aGF1c3RlZCA9IGZhbHNlLFxuICAgICAgZm9yd2FyZEV4aGF1c3RlZCA9IGZhbHNlLFxuICAgICAgbG9jYWxPZmZzZXQgPSAxO1xuXG4gIHJldHVybiBmdW5jdGlvbiBpdGVyYXRvcigpIHtcbiAgICBpZiAod2FudEZvcndhcmQgJiYgIWZvcndhcmRFeGhhdXN0ZWQpIHtcbiAgICAgIGlmIChiYWNrd2FyZEV4aGF1c3RlZCkge1xuICAgICAgICBsb2NhbE9mZnNldCsrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgd2FudEZvcndhcmQgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgaWYgdHJ5aW5nIHRvIGZpdCBiZXlvbmQgdGV4dCBsZW5ndGgsIGFuZCBpZiBub3QsIGNoZWNrIGl0IGZpdHNcbiAgICAgIC8vIGFmdGVyIG9mZnNldCBsb2NhdGlvbiAob3IgZGVzaXJlZCBsb2NhdGlvbiBvbiBmaXJzdCBpdGVyYXRpb24pXG4gICAgICBpZiAoc3RhcnQgKyBsb2NhbE9mZnNldCA8PSBtYXhMaW5lKSB7XG4gICAgICAgIHJldHVybiBsb2NhbE9mZnNldDtcbiAgICAgIH1cblxuICAgICAgZm9yd2FyZEV4aGF1c3RlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKCFiYWNrd2FyZEV4aGF1c3RlZCkge1xuICAgICAgaWYgKCFmb3J3YXJkRXhoYXVzdGVkKSB7XG4gICAgICAgIHdhbnRGb3J3YXJkID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgaWYgdHJ5aW5nIHRvIGZpdCBiZWZvcmUgdGV4dCBiZWdpbm5pbmcsIGFuZCBpZiBub3QsIGNoZWNrIGl0IGZpdHNcbiAgICAgIC8vIGJlZm9yZSBvZmZzZXQgbG9jYXRpb25cbiAgICAgIGlmIChtaW5MaW5lIDw9IHN0YXJ0IC0gbG9jYWxPZmZzZXQpIHtcbiAgICAgICAgcmV0dXJuIC1sb2NhbE9mZnNldCsrO1xuICAgICAgfVxuXG4gICAgICBiYWNrd2FyZEV4aGF1c3RlZCA9IHRydWU7XG4gICAgICByZXR1cm4gaXRlcmF0b3IoKTtcbiAgICB9XG5cbiAgICAvLyBXZSB0cmllZCB0byBmaXQgaHVuayBiZWZvcmUgdGV4dCBiZWdpbm5pbmcgYW5kIGJleW9uZCB0ZXh0IGxlbmd0aCwgdGhlblxuICAgIC8vIGh1bmsgY2FuJ3QgZml0IG9uIHRoZSB0ZXh0LiBSZXR1cm4gdW5kZWZpbmVkXG4gIH07XG59XG4iXX0=
diff --git a/node_modules/libtap/node_modules/diff/lib/util/params.js b/node_modules/libtap/node_modules/diff/lib/util/params.js
new file mode 100644
index 0000000000000..e838eb2f42d15
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/lib/util/params.js
@@ -0,0 +1,24 @@
+/*istanbul ignore start*/
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.generateOptions = generateOptions;
+
+/*istanbul ignore end*/
+function generateOptions(options, defaults) {
+  if (typeof options === 'function') {
+    defaults.callback = options;
+  } else if (options) {
+    for (var name in options) {
+      /* istanbul ignore else */
+      if (options.hasOwnProperty(name)) {
+        defaults[name] = options[name];
+      }
+    }
+  }
+
+  return defaults;
+}
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsL3BhcmFtcy5qcyJdLCJuYW1lcyI6WyJnZW5lcmF0ZU9wdGlvbnMiLCJvcHRpb25zIiwiZGVmYXVsdHMiLCJjYWxsYmFjayIsIm5hbWUiLCJoYXNPd25Qcm9wZXJ0eSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQU8sU0FBU0EsZUFBVCxDQUF5QkMsT0FBekIsRUFBa0NDLFFBQWxDLEVBQTRDO0FBQ2pELE1BQUksT0FBT0QsT0FBUCxLQUFtQixVQUF2QixFQUFtQztBQUNqQ0MsSUFBQUEsUUFBUSxDQUFDQyxRQUFULEdBQW9CRixPQUFwQjtBQUNELEdBRkQsTUFFTyxJQUFJQSxPQUFKLEVBQWE7QUFDbEIsU0FBSyxJQUFJRyxJQUFULElBQWlCSCxPQUFqQixFQUEwQjtBQUN4QjtBQUNBLFVBQUlBLE9BQU8sQ0FBQ0ksY0FBUixDQUF1QkQsSUFBdkIsQ0FBSixFQUFrQztBQUNoQ0YsUUFBQUEsUUFBUSxDQUFDRSxJQUFELENBQVIsR0FBaUJILE9BQU8sQ0FBQ0csSUFBRCxDQUF4QjtBQUNEO0FBQ0Y7QUFDRjs7QUFDRCxTQUFPRixRQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVPcHRpb25zKG9wdGlvbnMsIGRlZmF1bHRzKSB7XG4gIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGRlZmF1bHRzLmNhbGxiYWNrID0gb3B0aW9ucztcbiAgfSBlbHNlIGlmIChvcHRpb25zKSB7XG4gICAgZm9yIChsZXQgbmFtZSBpbiBvcHRpb25zKSB7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgaWYgKG9wdGlvbnMuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgZGVmYXVsdHNbbmFtZV0gPSBvcHRpb25zW25hbWVdO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gZGVmYXVsdHM7XG59XG4iXX0=
diff --git a/node_modules/libtap/node_modules/diff/package.json b/node_modules/libtap/node_modules/diff/package.json
new file mode 100644
index 0000000000000..3308b3278f199
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/package.json
@@ -0,0 +1,73 @@
+{
+  "name": "diff",
+  "version": "4.0.2",
+  "description": "A javascript text diff implementation.",
+  "keywords": [
+    "diff",
+    "javascript"
+  ],
+  "maintainers": [
+    "Kevin Decker  (http://incaseofstairs.com)"
+  ],
+  "bugs": {
+    "email": "kpdecker@gmail.com",
+    "url": "http://github.com/kpdecker/jsdiff/issues"
+  },
+  "license": "BSD-3-Clause",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/kpdecker/jsdiff.git"
+  },
+  "engines": {
+    "node": ">=0.3.1"
+  },
+  "main": "./lib/index.js",
+  "module": "./lib/index.es6.js",
+  "browser": "./dist/diff.js",
+  "scripts": {
+    "clean": "rm -rf lib/ dist/",
+    "build:node": "yarn babel --out-dir lib  --source-maps=inline src",
+    "test": "grunt"
+  },
+  "devDependencies": {
+    "@babel/cli": "^7.2.3",
+    "@babel/core": "^7.2.2",
+    "@babel/plugin-transform-modules-commonjs": "^7.2.0",
+    "@babel/preset-env": "^7.2.3",
+    "@babel/register": "^7.0.0",
+    "babel-eslint": "^10.0.1",
+    "babel-loader": "^8.0.5",
+    "chai": "^4.2.0",
+    "colors": "^1.3.3",
+    "eslint": "^5.12.0",
+    "grunt": "^1.0.3",
+    "grunt-babel": "^8.0.0",
+    "grunt-clean": "^0.4.0",
+    "grunt-cli": "^1.3.2",
+    "grunt-contrib-clean": "^2.0.0",
+    "grunt-contrib-copy": "^1.0.0",
+    "grunt-contrib-uglify": "^4.0.0",
+    "grunt-contrib-watch": "^1.1.0",
+    "grunt-eslint": "^21.0.0",
+    "grunt-exec": "^3.0.0",
+    "grunt-karma": "^3.0.1",
+    "grunt-mocha-istanbul": "^5.0.2",
+    "grunt-mocha-test": "^0.13.3",
+    "grunt-webpack": "^3.1.3",
+    "istanbul": "github:kpdecker/istanbul",
+    "karma": "^3.1.4",
+    "karma-chrome-launcher": "^2.2.0",
+    "karma-mocha": "^1.3.0",
+    "karma-mocha-reporter": "^2.0.0",
+    "karma-sauce-launcher": "^2.0.2",
+    "karma-sourcemap-loader": "^0.3.6",
+    "karma-webpack": "^3.0.5",
+    "mocha": "^5.2.0",
+    "rollup": "^1.0.2",
+    "rollup-plugin-babel": "^4.2.0",
+    "semver": "^5.6.0",
+    "webpack": "^4.28.3",
+    "webpack-dev-server": "^3.1.14"
+  },
+  "optionalDependencies": {}
+}
diff --git a/node_modules/libtap/node_modules/diff/release-notes.md b/node_modules/libtap/node_modules/diff/release-notes.md
new file mode 100644
index 0000000000000..edc4cd3842ef5
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/release-notes.md
@@ -0,0 +1,261 @@
+# Release Notes
+
+## Development
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v4.0.1...master)
+
+## v4.0.1 - January 6th, 2019
+- Fix main reference path - b826104
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v4.0.0...v4.0.1)
+
+## v4.0.0 - January 5th, 2019
+- [#94](https://github.com/kpdecker/jsdiff/issues/94) - Missing "No newline at end of file" when comparing two texts that do not end in newlines ([@federicotdn](https://api.github.com/users/federicotdn))
+- [#227](https://github.com/kpdecker/jsdiff/issues/227) - Licence
+- [#199](https://github.com/kpdecker/jsdiff/issues/199) - Import statement for jsdiff
+- [#159](https://github.com/kpdecker/jsdiff/issues/159) - applyPatch affecting wrong line number with with new lines
+- [#8](https://github.com/kpdecker/jsdiff/issues/8) - A new state "replace"
+- Drop ie9 from karma targets - 79c31bd
+- Upgrade deps. Convert from webpack to rollup - 2c1a29c
+- Make ()[]"' as word boundaries between each other - f27b899
+- jsdiff: Replaced phantomJS by chrome - ec3114e
+- Add yarn.lock to .npmignore - 29466d8
+
+Compatibility notes:
+- Bower and Component packages no longer supported
+
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v3.5.0...v4.0.0)
+
+## v3.5.0 - March 4th, 2018
+- Omit redundant slice in join method of diffArrays - 1023590
+- Support patches with empty lines - fb0f208
+- Accept a custom JSON replacer function for JSON diffing - 69c7f0a
+- Optimize parch header parser - 2aec429
+- Fix typos - e89c832
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v3.4.0...v3.5.0)
+
+## v3.4.0 - October 7th, 2017
+- [#183](https://github.com/kpdecker/jsdiff/issues/183) - Feature request: ability to specify a custom equality checker for `diffArrays`
+- [#173](https://github.com/kpdecker/jsdiff/issues/173) - Bug: diffArrays gives wrong result on array of booleans
+- [#158](https://github.com/kpdecker/jsdiff/issues/158) - diffArrays will not compare the empty string in array?
+- comparator for custom equality checks - 30e141e
+- count oldLines and newLines when there are conflicts - 53bf384
+- Fix: diffArrays can compare falsey items - 9e24284
+- Docs: Replace grunt with npm test - 00e2f94
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v3.3.1...v3.4.0)
+
+## v3.3.1 - September 3rd, 2017
+- [#141](https://github.com/kpdecker/jsdiff/issues/141) - Cannot apply patch because my file delimiter is "/r/n" instead of "/n"
+- [#192](https://github.com/kpdecker/jsdiff/pull/192) - Fix: Bad merge when adding new files (#189)
+- correct spelling mistake - 21fa478
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v3.3.0...v3.3.1)
+
+## v3.3.0 - July 5th, 2017
+- [#114](https://github.com/kpdecker/jsdiff/issues/114) - /patch/merge not exported
+- Gracefully accept invalid newStart in hunks, same as patch(1) does. - d8a3635
+- Use regex rather than starts/ends with for parsePatch - 6cab62c
+- Add browser flag - e64f674
+- refactor: simplified code a bit more - 8f8e0f2
+- refactor: simplified code a bit - b094a6f
+- fix: some corrections re ignoreCase option - 3c78fd0
+- ignoreCase option - 3cbfbb5
+- Sanitize filename while parsing patches - 2fe8129
+- Added better installation methods - aced50b
+- Simple export of functionality - 8690f31
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v3.2.0...v3.3.0)
+
+## v3.2.0 - December 26th, 2016
+- [#156](https://github.com/kpdecker/jsdiff/pull/156) - Add `undefinedReplacement` option to `diffJson` ([@ewnd9](https://api.github.com/users/ewnd9))
+- [#154](https://github.com/kpdecker/jsdiff/pull/154) - Add `examples` and `images` to `.npmignore`. ([@wtgtybhertgeghgtwtg](https://api.github.com/users/wtgtybhertgeghgtwtg))
+- [#153](https://github.com/kpdecker/jsdiff/pull/153) - feat(structuredPatch): Pass options to diffLines ([@Kiougar](https://api.github.com/users/Kiougar))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v3.1.0...v3.2.0)
+
+## v3.1.0 - November 27th, 2016
+- [#146](https://github.com/kpdecker/jsdiff/pull/146) - JsDiff.diffArrays to compare arrays ([@wvanderdeijl](https://api.github.com/users/wvanderdeijl))
+- [#144](https://github.com/kpdecker/jsdiff/pull/144) - Split file using all possible line delimiter instead of hard-coded "/n" and join lines back using the original delimiters ([@soulbeing](https://api.github.com/users/soulbeing))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v3.0.1...v3.1.0)
+
+## v3.0.1 - October 9th, 2016
+- [#139](https://github.com/kpdecker/jsdiff/pull/139) - Make README.md look nicer in npmjs.com ([@takenspc](https://api.github.com/users/takenspc))
+- [#135](https://github.com/kpdecker/jsdiff/issues/135) - parsePatch combines patches from multiple files into a single IUniDiff when there is no "Index" line ([@ramya-rao-a](https://api.github.com/users/ramya-rao-a))
+- [#124](https://github.com/kpdecker/jsdiff/issues/124) - IE7/IE8 failure since 2.0.0 ([@boneskull](https://api.github.com/users/boneskull))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v3.0.0...v3.0.1)
+
+## v3.0.0 - August 23rd, 2016
+- [#130](https://github.com/kpdecker/jsdiff/pull/130) - Add callback argument to applyPatches `patched` option ([@piranna](https://api.github.com/users/piranna))
+- [#120](https://github.com/kpdecker/jsdiff/pull/120) - Correctly handle file names containing spaces ([@adius](https://api.github.com/users/adius))
+- [#119](https://github.com/kpdecker/jsdiff/pull/119) - Do single reflow ([@wifiextender](https://api.github.com/users/wifiextender))
+- [#117](https://github.com/kpdecker/jsdiff/pull/117) - Make more usable with long strings. ([@abnbgist](https://api.github.com/users/abnbgist))
+
+Compatibility notes:
+- applyPatches patch callback now is async and requires the callback be called to continue operation
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v2.2.3...v3.0.0)
+
+## v2.2.3 - May 31st, 2016
+- [#118](https://github.com/kpdecker/jsdiff/pull/118) - Add a fix for applying 0-length destination patches ([@chaaz](https://api.github.com/users/chaaz))
+- [#115](https://github.com/kpdecker/jsdiff/pull/115) - Fixed grammar in README ([@krizalys](https://api.github.com/users/krizalys))
+- [#113](https://github.com/kpdecker/jsdiff/pull/113) - fix typo ([@vmazare](https://api.github.com/users/vmazare))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v2.2.2...v2.2.3)
+
+## v2.2.2 - March 13th, 2016
+- [#102](https://github.com/kpdecker/jsdiff/issues/102) - diffJson with dates, returns empty curly braces  ([@dr-dimitru](https://api.github.com/users/dr-dimitru))
+- [#97](https://github.com/kpdecker/jsdiff/issues/97) - Whitespaces & diffWords ([@faiwer](https://api.github.com/users/faiwer))
+- [#92](https://github.com/kpdecker/jsdiff/pull/92) - Fixes typo in the readme ([@bg451](https://api.github.com/users/bg451))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v2.2.1...v2.2.2)
+
+## v2.2.1 - November 12th, 2015
+- [#89](https://github.com/kpdecker/jsdiff/pull/89) - add in display selector to readme ([@FranDias](https://api.github.com/users/FranDias))
+- [#88](https://github.com/kpdecker/jsdiff/pull/88) - Split diffs based on file headers instead of 'Index:' metadata ([@piranna](https://api.github.com/users/piranna))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v2.2.0...v2.2.1)
+
+## v2.2.0 - October 29th, 2015
+- [#80](https://github.com/kpdecker/jsdiff/pull/80) - Fix a typo: applyPath ->  applyPatch ([@fluxxu](https://api.github.com/users/fluxxu))
+- [#83](https://github.com/kpdecker/jsdiff/pull/83) - Add basic fuzzy matching to applyPatch ([@piranna](https://github.com/piranna))
+[Commits](https://github.com/kpdecker/jsdiff/compare/v2.2.0...v2.2.0)
+
+## v2.2.0 - October 29th, 2015
+- [#80](https://github.com/kpdecker/jsdiff/pull/80) - Fix a typo: applyPath ->  applyPatch ([@fluxxu](https://api.github.com/users/fluxxu))
+- [#83](https://github.com/kpdecker/jsdiff/pull/83) - Add basic fuzzy matching to applyPatch ([@piranna](https://github.com/piranna))
+[Commits](https://github.com/kpdecker/jsdiff/compare/v2.1.3...v2.2.0)
+
+## v2.1.3 - September 30th, 2015
+- [#78](https://github.com/kpdecker/jsdiff/pull/78) - fix: error throwing when apply patch to empty string ([@21paradox](https://api.github.com/users/21paradox))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v2.1.2...v2.1.3)
+
+## v2.1.2 - September 23rd, 2015
+- [#76](https://github.com/kpdecker/jsdiff/issues/76) - diff headers give error ([@piranna](https://api.github.com/users/piranna))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v2.1.1...v2.1.2)
+
+## v2.1.1 - September 9th, 2015
+- [#73](https://github.com/kpdecker/jsdiff/issues/73) - Is applyPatches() exposed in the API? ([@davidparsson](https://api.github.com/users/davidparsson))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v2.1.0...v2.1.1)
+
+## v2.1.0 - August 27th, 2015
+- [#72](https://github.com/kpdecker/jsdiff/issues/72) - Consider using options object API for flag permutations ([@kpdecker](https://api.github.com/users/kpdecker))
+- [#70](https://github.com/kpdecker/jsdiff/issues/70) - diffWords treats \n at the end as significant whitespace ([@nesQuick](https://api.github.com/users/nesQuick))
+- [#69](https://github.com/kpdecker/jsdiff/issues/69) - Missing count ([@wfalkwallace](https://api.github.com/users/wfalkwallace))
+- [#68](https://github.com/kpdecker/jsdiff/issues/68) - diffLines seems broken ([@wfalkwallace](https://api.github.com/users/wfalkwallace))
+- [#60](https://github.com/kpdecker/jsdiff/issues/60) - Support multiple diff hunks ([@piranna](https://api.github.com/users/piranna))
+- [#54](https://github.com/kpdecker/jsdiff/issues/54) - Feature Request: 3-way merge ([@mog422](https://api.github.com/users/mog422))
+- [#42](https://github.com/kpdecker/jsdiff/issues/42) - Fuzz factor for applyPatch ([@stuartpb](https://api.github.com/users/stuartpb))
+- Move whitespace ignore out of equals method - 542063c
+- Include source maps in babel output - 7f7ab21
+- Merge diff/line and diff/patch implementations - 1597705
+- Drop map utility method - 1ddc939
+- Documentation for parsePatch and applyPatches - 27c4b77
+
+Compatibility notes:
+- The undocumented ignoreWhitespace flag has been removed from the Diff equality check directly. This implementation may be copied to diff utilities if dependencies existed on this functionality.
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v2.0.2...v2.1.0)
+
+## v2.0.2 - August 8th, 2015
+- [#67](https://github.com/kpdecker/jsdiff/issues/67) - cannot require from npm module in node ([@commenthol](https://api.github.com/users/commenthol))
+- Convert to chai since we don’t support IE8 - a96bbad
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v2.0.1...v2.0.2)
+
+## v2.0.1 - August 7th, 2015
+- Add release build at proper step - 57542fd
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v2.0.0...v2.0.1)
+
+## v2.0.0 - August 7th, 2015
+- [#66](https://github.com/kpdecker/jsdiff/issues/66) - Add karma and sauce tests ([@kpdecker](https://api.github.com/users/kpdecker))
+- [#65](https://github.com/kpdecker/jsdiff/issues/65) - Create component repository for bower ([@kpdecker](https://api.github.com/users/kpdecker))
+- [#64](https://github.com/kpdecker/jsdiff/issues/64) - Automatically call removeEmpty for all tokenizer calls ([@kpdecker](https://api.github.com/users/kpdecker))
+- [#62](https://github.com/kpdecker/jsdiff/pull/62) - Allow access to structured object representation of patch data ([@bittrance](https://api.github.com/users/bittrance))
+- [#61](https://github.com/kpdecker/jsdiff/pull/61) - Use svg instead of png to get better image quality ([@PeterDaveHello](https://api.github.com/users/PeterDaveHello))
+- [#29](https://github.com/kpdecker/jsdiff/issues/29) - word tokenizer works only for 7 bit ascii ([@plasmagunman](https://api.github.com/users/plasmagunman))
+
+Compatibility notes:
+- `this.removeEmpty` is now called automatically for all instances. If this is not desired, this may be overridden on a per instance basis.
+- The library has been refactored to use some ES6 features. The external APIs should remain the same, but bower projects that directly referenced the repository will now have to point to the [components/jsdiff](https://github.com/components/jsdiff) repository.
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v1.4.0...v2.0.0)
+
+## v1.4.0 - May 6th, 2015
+- [#57](https://github.com/kpdecker/jsdiff/issues/57) - createPatch -> applyPatch failed. ([@mog422](https://api.github.com/users/mog422))
+- [#56](https://github.com/kpdecker/jsdiff/pull/56) - Two files patch ([@rgeissert](https://api.github.com/users/rgeissert))
+- [#14](https://github.com/kpdecker/jsdiff/issues/14) - Flip added and removed order? ([@jakesandlund](https://api.github.com/users/jakesandlund))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v1.3.2...v1.4.0)
+
+## v1.3.2 - March 30th, 2015
+- [#53](https://github.com/kpdecker/jsdiff/pull/53) - Updated README.MD with Bower installation instructions ([@ofbriggs](https://api.github.com/users/ofbriggs))
+- [#49](https://github.com/kpdecker/jsdiff/issues/49) - Cannot read property 'oldlines' of undefined ([@nwtn](https://api.github.com/users/nwtn))
+- [#44](https://github.com/kpdecker/jsdiff/issues/44) - invalid-meta jsdiff is missing "main" entry in bower.json
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v1.3.1...v1.3.2)
+
+## v1.3.1 - March 13th, 2015
+- [#52](https://github.com/kpdecker/jsdiff/pull/52) - Fix for #51 Wrong result of JsDiff.diffLines ([@felicienfrancois](https://api.github.com/users/felicienfrancois))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v1.3.0...v1.3.1)
+
+## v1.3.0 - March 2nd, 2015
+- [#47](https://github.com/kpdecker/jsdiff/pull/47) - Adding Diff Trimmed Lines ([@JamesGould123](https://api.github.com/users/JamesGould123))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v1.2.2...v1.3.0)
+
+## v1.2.2 - January 26th, 2015
+- [#45](https://github.com/kpdecker/jsdiff/pull/45) - Fix AMD module loading ([@pedrocarrico](https://api.github.com/users/pedrocarrico))
+- [#43](https://github.com/kpdecker/jsdiff/pull/43) - added a bower file ([@nbrustein](https://api.github.com/users/nbrustein))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v1.2.1...v1.2.2)
+
+## v1.2.1 - December 26th, 2014
+- [#41](https://github.com/kpdecker/jsdiff/pull/41) - change condition of using node export system. ([@ironhee](https://api.github.com/users/ironhee))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v1.2.0...v1.2.1)
+
+## v1.2.0 - November 29th, 2014
+- [#37](https://github.com/kpdecker/jsdiff/pull/37) - Add support for sentences. ([@vmariano](https://api.github.com/users/vmariano))
+- [#28](https://github.com/kpdecker/jsdiff/pull/28) - Implemented diffJson ([@papandreou](https://api.github.com/users/papandreou))
+- [#27](https://github.com/kpdecker/jsdiff/issues/27) - Slow to execute over diffs with a large number of changes ([@termi](https://api.github.com/users/termi))
+- Allow for optional async diffing - 19385b9
+- Fix diffChars implementation - eaa44ed
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v1.1.0...v1.2.0)
+
+## v1.1.0 - November 25th, 2014
+- [#33](https://github.com/kpdecker/jsdiff/pull/33) - AMD and global exports ([@ovcharik](https://api.github.com/users/ovcharik))
+- [#32](https://github.com/kpdecker/jsdiff/pull/32) - Add support for component ([@vmariano](https://api.github.com/users/vmariano))
+- [#31](https://github.com/kpdecker/jsdiff/pull/31) - Don't rely on Array.prototype.map ([@papandreou](https://api.github.com/users/papandreou))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v1.0.8...v1.1.0)
+
+## v1.0.8 - December 22nd, 2013
+- [#24](https://github.com/kpdecker/jsdiff/pull/24) - Handle windows newlines on non windows machines. ([@benogle](https://api.github.com/users/benogle))
+- [#23](https://github.com/kpdecker/jsdiff/pull/23) - Prettied up the API formatting a little, and added basic node and web examples ([@airportyh](https://api.github.com/users/airportyh))
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v1.0.7...v1.0.8)
+
+## v1.0.7 - September 11th, 2013
+
+- [#22](https://github.com/kpdecker/jsdiff/pull/22) - Added variant of WordDiff that doesn't ignore whitespace differences ([@papandreou](https://api.github.com/users/papandreou)
+
+- Add 0.10 to travis tests - 243a526
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v1.0.6...v1.0.7)
+
+## v1.0.6 - August 30th, 2013
+
+- [#19](https://github.com/kpdecker/jsdiff/pull/19) - Explicitly define contents of npm package ([@sindresorhus](https://api.github.com/users/sindresorhus)
+
+[Commits](https://github.com/kpdecker/jsdiff/compare/v1.0.5...v1.0.6)
diff --git a/node_modules/libtap/node_modules/diff/runtime.js b/node_modules/libtap/node_modules/diff/runtime.js
new file mode 100644
index 0000000000000..82ea7e696aa01
--- /dev/null
+++ b/node_modules/libtap/node_modules/diff/runtime.js
@@ -0,0 +1,3 @@
+require('@babel/register')({
+  ignore: ['lib', 'node_modules']
+});
diff --git a/node_modules/libtap/package.json b/node_modules/libtap/package.json
new file mode 100644
index 0000000000000..f6a658a33e3dc
--- /dev/null
+++ b/node_modules/libtap/package.json
@@ -0,0 +1,72 @@
+{
+  "name": "libtap",
+  "version": "1.1.1",
+  "author": "Isaac Z. Schlueter  (http://blog.izs.me)",
+  "description": "A Test-Anything-Protocol library for JavaScript",
+  "homepage": "http://www.node-tap.org/",
+  "main": "lib/tap.js",
+  "exports": {
+    ".": {
+      "import": "./lib/tap.mjs",
+      "default": "./lib/tap.js"
+    },
+    "./settings": "./settings.js",
+    "./versions": "./versions.js"
+  },
+  "engines": {
+    "node": ">=10"
+  },
+  "dependencies": {
+    "async-hook-domain": "^2.0.1",
+    "bind-obj-methods": "^3.0.0",
+    "diff": "^4.0.2",
+    "function-loop": "^2.0.1",
+    "minipass": "^3.1.1",
+    "own-or": "^1.0.0",
+    "own-or-env": "^1.0.1",
+    "signal-exit": "^3.0.2",
+    "stack-utils": "^2.0.1",
+    "tap-parser": "^10.0.1",
+    "tap-yaml": "^1.0.0",
+    "tcompare": "^5.0.1",
+    "trivial-deferred": "^1.0.1",
+    "yapool": "^1.0.0"
+  },
+  "devDependencies": {
+    "@babel/core": "^7.8.7",
+    "@istanbuljs/esm-loader-hook": "^0.1.0",
+    "foreground-child": "^2.0.0",
+    "glob": "^7.1.6",
+    "nyc": "^15.0.0",
+    "rimraf": "^3.0.0",
+    "semver": "^7.1.3",
+    "source-map-support": "^0.5.16",
+    "tap-mocha-reporter": "^5.0.1"
+  },
+  "keywords": [
+    "assert",
+    "tap",
+    "test",
+    "testing"
+  ],
+  "license": "ISC",
+  "repository": "https://github.com/tapjs/libtap.git",
+  "scripts": {
+    "presnap": "rimraf tap-snapshots",
+    "snap": "TAP_SNAPSHOT=1 npm test",
+    "tests-only": "nyc --silent=true --no-check-coverage node npm-run-test.js | tap-mocha-reporter classic",
+    "test": "npm run -s tests-only",
+    "posttest": "nyc report",
+    "preversion": "npm test",
+    "postversion": "npm publish",
+    "prepublishOnly": "git push origin --follow-tags"
+  },
+  "files": [
+    "settings.js",
+    "versions.js",
+    "lib"
+  ],
+  "funding": {
+    "url": "https://github.com/sponsors/isaacs"
+  }
+}
diff --git a/node_modules/libtap/settings.js b/node_modules/libtap/settings.js
new file mode 100644
index 0000000000000..0badd5c752cd1
--- /dev/null
+++ b/node_modules/libtap/settings.js
@@ -0,0 +1,133 @@
+'use strict'
+
+const fs = require('fs')
+const path = require('path')
+const StackUtils = require('stack-utils')
+
+// Just unconditionally use fs.rmdirSync after LTS/12 is required
+let rmdirRecursiveSync
+let rmdirRecursive
+let hasFsRm = false
+let mkdirRecursive
+let mkdirRecursiveSync
+
+module.exports = {
+  atTap: false,
+
+  get mkdirpNeeded() {
+    const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(Number)
+    /* istanbul ignore next: version specific */
+    return !mkdirRecursiveSync && (nodeMajor < 10 || (nodeMajor === 10 && nodeMinor < 12))
+  },
+
+  get mkdirRecursive() {
+    /* istanbul ignore next: version specific */
+    if (!mkdirRecursive) {
+      return () => {
+        throw new Error("require('libtap/settings').mkdirRecursive must be initialized for Node.js <10.12.0")
+      }
+    }
+
+    return mkdirRecursive
+  },
+
+  set mkdirRecursive(value) {
+    if (typeof value !== 'function' || value.length !== 2) {
+      throw new TypeError('mkdirRecursive must be a function with exactly two arguments')
+    }
+
+    mkdirRecursive = value
+  },
+
+  get mkdirRecursiveSync() {
+    /* istanbul ignore next: version specific */
+    if (!mkdirRecursiveSync) {
+      return () => {
+        throw new Error("require('libtap/settings').mkdirRecursiveSync must be initialized for Node.js <10.12.0")
+      }
+    }
+
+    return mkdirRecursiveSync
+  },
+
+  set mkdirRecursiveSync(value) {
+    if (typeof value !== 'function' || value.length !== 1) {
+      throw new TypeError('mkdirRecursiveSync must be a function with exactly one argument')
+    }
+
+    mkdirRecursiveSync = value
+  },
+
+  get rimrafNeeded() {
+    const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(Number)
+    /* istanbul ignore next: version specific */
+    hasFsRm = (nodeMajor === 14 && nodeMinor >= 14) || nodeMajor >= 15
+    /* istanbul ignore next: version specific */
+    return !rmdirRecursiveSync && (nodeMajor < 12 || (nodeMajor === 12 && nodeMinor < 10))
+  },
+
+  get rmdirRecursive() {
+    /* istanbul ignore next: version specific */
+    if (!rmdirRecursive) {
+      return () => {
+        throw new Error("require('libtap/settings').rmdirRecursive must be initialized for Node.js <12.10.0")
+      }
+    }
+
+    return rmdirRecursive
+  },
+
+  set rmdirRecursive(value) {
+    if (typeof value !== 'function' || value.length !== 2) {
+      throw new TypeError('rmdirRecursive must be a function with exactly two arguments')
+    }
+
+    rmdirRecursive = value
+  },
+
+  get rmdirRecursiveSync() {
+    /* istanbul ignore next: version specific */
+    if (!rmdirRecursiveSync) {
+      return () => {
+        throw new Error("require('libtap/settings').rmdirRecursiveSync must be initialized for Node.js <12.10.0")
+      }
+    }
+
+    return rmdirRecursiveSync
+  },
+
+  set rmdirRecursiveSync(value) {
+    if (typeof value !== 'function' || value.length !== 1) {
+      throw new TypeError('rmdirRecursiveSync must be a function with exactly one argument')
+    }
+
+    rmdirRecursiveSync = value
+  },
+
+  StackUtils,
+  stackUtils: {
+    // Support `settings.stackUtils.internals.push()`
+    internals: StackUtils.nodeInternals(),
+    ignoredPackages: []
+  },
+  output: process.stdout,
+  snapshotFile: (cwd, main, argv) => {
+    return path.resolve(cwd, 'tap-snapshots', main + argv + '.test.cjs')
+  }
+}
+
+/* istanbul ignore next: version specific */
+if (!module.exports.rimrafNeeded) {
+  const fs = require('fs')
+  const rm = hasFsRm ? 'rm' : 'rmdir'
+  const rmSync = `${rm}Sync`
+  rmdirRecursiveSync = dir => fs[rmSync](dir, {recursive: true, force: true})
+  rmdirRecursive = (dir, cb) => fs[rm](dir, {recursive: true, force: true}, cb)
+}
+
+/* istanbul ignore next: version specific */
+if (!module.exports.mkdirpNeeded) {
+  const { mkdir, mkdirSync } = require('fs')
+  mkdirRecursiveSync = dir => mkdirSync(dir, { recursive: true })
+  mkdirRecursive = (dir, cb) => mkdir(dir, { recursive: true }, cb)
+}
diff --git a/node_modules/libtap/versions.js b/node_modules/libtap/versions.js
new file mode 100644
index 0000000000000..409f240907f6e
--- /dev/null
+++ b/node_modules/libtap/versions.js
@@ -0,0 +1,8 @@
+'use strict'
+
+module.exports = {
+  libtap: require('./package.json').version,
+  tapParser: require('tap-parser/package.json').version,
+  tapYaml: require('tap-yaml/package.json').version,
+  tcompare: require('tcompare/package.json').version
+}
diff --git a/node_modules/mime-db/HISTORY.md b/node_modules/mime-db/HISTORY.md
index aff74740dc55e..1555055e8a795 100644
--- a/node_modules/mime-db/HISTORY.md
+++ b/node_modules/mime-db/HISTORY.md
@@ -1,3 +1,10 @@
+1.47.0 / 2021-04-01
+===================
+
+  * Add new upstream MIME types
+  * Remove ambigious extensions from IANA for `application/*+xml` types
+  * Update primary extension to `.es` for `application/ecmascript`
+
 1.46.0 / 2021-02-13
 ===================
 
diff --git a/node_modules/mime-db/README.md b/node_modules/mime-db/README.md
index 8f1d8c4e53ffd..41c696a30dfa1 100644
--- a/node_modules/mime-db/README.md
+++ b/node_modules/mime-db/README.md
@@ -34,8 +34,6 @@ https://cdn.jsdelivr.net/gh/jshttp/mime-db@master/db.json
 
 ## Usage
 
-
-
 ```js
 var db = require('mime-db')
 
diff --git a/node_modules/mime-db/db.json b/node_modules/mime-db/db.json
index 4871607a58a98..63c189ea2687b 100644
--- a/node_modules/mime-db/db.json
+++ b/node_modules/mime-db/db.json
@@ -389,7 +389,7 @@
   "application/ecmascript": {
     "source": "iana",
     "compressible": true,
-    "extensions": ["ecma","es"]
+    "extensions": ["es","ecma"]
   },
   "application/edi-consent": {
     "source": "iana"
@@ -934,13 +934,11 @@
   },
   "application/mrb-consumer+xml": {
     "source": "iana",
-    "compressible": true,
-    "extensions": ["xdf"]
+    "compressible": true
   },
   "application/mrb-publish+xml": {
     "source": "iana",
-    "compressible": true,
-    "extensions": ["xdf"]
+    "compressible": true
   },
   "application/msc-ivr+xml": {
     "source": "iana",
@@ -2321,6 +2319,9 @@
   "application/vnd.crypto-shade-file": {
     "source": "iana"
   },
+  "application/vnd.cryptomator.encrypted": {
+    "source": "iana"
+  },
   "application/vnd.ctc-posml": {
     "source": "iana",
     "extensions": ["pml"]
@@ -3786,6 +3787,9 @@
     "source": "iana",
     "compressible": true
   },
+  "application/vnd.nebumind.line": {
+    "source": "iana"
+  },
   "application/vnd.nervana": {
     "source": "iana"
   },
@@ -6071,8 +6075,7 @@
   },
   "application/xcap-error+xml": {
     "source": "iana",
-    "compressible": true,
-    "extensions": ["xer"]
+    "compressible": true
   },
   "application/xcap-ns+xml": {
     "source": "iana",
@@ -7400,6 +7403,10 @@
   "model/vnd.rosette.annotated-data-model": {
     "source": "iana"
   },
+  "model/vnd.sap.vds": {
+    "source": "iana",
+    "extensions": ["vds"]
+  },
   "model/vnd.usdz+zip": {
     "source": "iana",
     "compressible": false,
@@ -7980,6 +7987,9 @@
   "video/encaprtp": {
     "source": "iana"
   },
+  "video/ffv1": {
+    "source": "iana"
+  },
   "video/flexfec": {
     "source": "iana"
   },
diff --git a/node_modules/mime-db/package.json b/node_modules/mime-db/package.json
index ec0328404d949..bd6403fb68f9f 100644
--- a/node_modules/mime-db/package.json
+++ b/node_modules/mime-db/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mime-db",
   "description": "Media Type Database",
-  "version": "1.46.0",
+  "version": "1.47.0",
   "contributors": [
     "Douglas Christopher Wilson ",
     "Jonathan Ong  (http://jongleberry.com)",
@@ -22,16 +22,16 @@
     "bluebird": "3.7.2",
     "co": "4.6.0",
     "cogent": "1.0.1",
-    "csv-parse": "4.15.1",
-    "eslint": "7.20.0",
+    "csv-parse": "4.15.3",
+    "eslint": "7.23.0",
     "eslint-config-standard": "15.0.1",
     "eslint-plugin-import": "2.22.1",
-    "eslint-plugin-markdown": "1.0.2",
+    "eslint-plugin-markdown": "2.0.0",
     "eslint-plugin-node": "11.1.0",
     "eslint-plugin-promise": "4.3.1",
     "eslint-plugin-standard": "4.1.0",
     "gnode": "0.1.2",
-    "mocha": "8.3.0",
+    "mocha": "8.3.2",
     "nyc": "15.1.0",
     "raw-body": "2.4.1",
     "stream-to-array": "2.3.0"
@@ -49,7 +49,7 @@
   "scripts": {
     "build": "node scripts/build",
     "fetch": "node scripts/fetch-apache && gnode scripts/fetch-iana && node scripts/fetch-nginx",
-    "lint": "eslint --plugin markdown --ext js,md .",
+    "lint": "eslint .",
     "test": "mocha --reporter spec --bail --check-leaks test/",
     "test-ci": "nyc --reporter=lcov --reporter=text npm test",
     "test-cov": "nyc --reporter=html --reporter=text npm test",
diff --git a/node_modules/mime-types/HISTORY.md b/node_modules/mime-types/HISTORY.md
index 2e50fc84a4d88..38472bee131e4 100644
--- a/node_modules/mime-types/HISTORY.md
+++ b/node_modules/mime-types/HISTORY.md
@@ -1,3 +1,11 @@
+2.1.30 / 2021-04-02
+===================
+
+  * deps: mime-db@1.47.0
+    - Add extension `.amr` to `audio/amr`
+    - Remove ambigious extensions from IANA for `application/*+xml` types
+    - Update primary extension to `.es` for `application/ecmascript`
+
 2.1.29 / 2021-02-17
 ===================
 
diff --git a/node_modules/mime-types/package.json b/node_modules/mime-types/package.json
index 9ed59e843e726..ea53dd22aa1d3 100644
--- a/node_modules/mime-types/package.json
+++ b/node_modules/mime-types/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mime-types",
   "description": "The ultimate javascript content-type utility.",
-  "version": "2.1.29",
+  "version": "2.1.30",
   "contributors": [
     "Douglas Christopher Wilson ",
     "Jeremiah Senkpiel  (https://searchbeam.jit.su)",
@@ -14,17 +14,17 @@
   ],
   "repository": "jshttp/mime-types",
   "dependencies": {
-    "mime-db": "1.46.0"
+    "mime-db": "1.47.0"
   },
   "devDependencies": {
-    "eslint": "7.20.0",
+    "eslint": "7.23.0",
     "eslint-config-standard": "14.1.1",
     "eslint-plugin-import": "2.22.1",
     "eslint-plugin-markdown": "2.0.0",
     "eslint-plugin-node": "11.1.0",
     "eslint-plugin-promise": "4.3.1",
     "eslint-plugin-standard": "4.1.0",
-    "mocha": "8.3.0",
+    "mocha": "8.3.2",
     "nyc": "15.1.0"
   },
   "files": [
diff --git a/node_modules/node-preload/CHANGELOG.md b/node_modules/node-preload/CHANGELOG.md
new file mode 100644
index 0000000000000..ff3666cb33367
--- /dev/null
+++ b/node_modules/node-preload/CHANGELOG.md
@@ -0,0 +1,61 @@
+# 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.
+
+### [0.2.1](https://github.com/cfware/node-preload/compare/v0.2.0...v0.2.1) (2019-12-22)
+
+
+### Bug Fixes
+
+* Support jumping between node.js versions ([#7](https://github.com/cfware/node-preload/issues/7)) ([68950a0](https://github.com/cfware/node-preload/commit/68950a07ab153cda5e0b5fec1407973169443bbb)), closes [istanbuljs/nyc#1246](https://github.com/istanbuljs/nyc/issues/1246)
+
+## [0.2.0](https://github.com/cfware/node-preload/compare/v0.1.4...v0.2.0) (2019-12-16)
+
+
+### ⚠ BREAKING CHANGES
+
+* The API is completely rewritten, the export is now an
+Array.
+* Propagated variables are no longer supported.  For this
+functionality preload a local module which uses `process-on-spawn`
+directly.
+
+### Features
+
+* Use process-on-spawn ([#6](https://github.com/cfware/node-preload/issues/6)) ([2decb3a](https://github.com/cfware/node-preload/commit/2decb3a32a00084d089d964de6440e9f7817d563))
+
+## [0.1.4](https://github.com/cfware/node-preload/compare/v0.1.3...v0.1.4) (2019-11-01)
+
+
+### Features
+
+* Support running under yarn pnp ([#3](https://github.com/cfware/node-preload/issues/3)) ([15d949b](https://github.com/cfware/node-preload/commit/15d949b)), closes [istanbuljs/nyc#1204](https://github.com/istanbuljs/nyc/issues/1204)
+
+## [0.1.3](https://github.com/cfware/node-preload/compare/v0.1.2...v0.1.3) (2019-10-07)
+
+
+### Bug Fixes
+
+* Properly handle backslashes in paths on Node.js 12 ([#2](https://github.com/cfware/node-preload/issues/2)) ([2ad4448](https://github.com/cfware/node-preload/commit/2ad4448))
+
+## [0.1.2](https://github.com/cfware/node-preload/compare/v0.1.1...v0.1.2) (2019-09-24)
+
+
+### Bug Fixes
+
+* esm must be loaded from the internal/preload module ([a5444dd](https://github.com/cfware/node-preload/commit/a5444dd))
+
+## [0.1.1](https://github.com/cfware/node-preload/compare/v0.1.0...v0.1.1) (2019-09-23)
+
+
+### Bug Fixes
+
+* Add `main` to package.json ([6b39401](https://github.com/cfware/node-preload/commit/6b39401))
+* Handle situations where a preload might require node-preload. ([3b41164](https://github.com/cfware/node-preload/commit/3b41164))
+
+## 0.1.0 (2019-09-23)
+
+
+### Features
+
+* Initial implementation ([0818e8c](https://github.com/cfware/node-preload/commit/0818e8c))
diff --git a/node_modules/node-preload/LICENSE b/node_modules/node-preload/LICENSE
new file mode 100644
index 0000000000000..807a18bdbcb7d
--- /dev/null
+++ b/node_modules/node-preload/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 CFWare, LLC
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/node-preload/README.md b/node_modules/node-preload/README.md
new file mode 100644
index 0000000000000..de8e80d546536
--- /dev/null
+++ b/node_modules/node-preload/README.md
@@ -0,0 +1,47 @@
+# node-preload
+
+[![Travis CI][travis-image]][travis-url]
+[![Greenkeeper badge][gk-image]](https://greenkeeper.io/)
+[![NPM Version][npm-image]][npm-url]
+[![NPM Downloads][downloads-image]][downloads-url]
+[![MIT][license-image]](LICENSE)
+
+Request that Node.js child processes preload modules
+
+### Install node-preload
+
+This module requires node.js 8 or above.
+
+```sh
+npm i node-preload
+```
+
+## Usage
+
+```js
+'use strict';
+
+const preloadList = require('node-preload');
+
+// Request that all Node.js child processes preload @babel/register
+preloadList.push(require.resolve('@babel/register'));
+```
+
+## Limitations
+
+Worker threads are not directly supported by this module, results may vary.
+
+## `node-preload` for enterprise
+
+Available as part of the Tidelift Subscription.
+
+The maintainers of `node-preload` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-node-preload?utm_source=npm-node-preload&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
+
+[npm-image]: https://img.shields.io/npm/v/node-preload.svg
+[npm-url]: https://npmjs.org/package/node-preload
+[travis-image]: https://travis-ci.org/cfware/node-preload.svg?branch=master
+[travis-url]: https://travis-ci.org/cfware/node-preload
+[gk-image]: https://badges.greenkeeper.io/cfware/node-preload.svg
+[downloads-image]: https://img.shields.io/npm/dm/node-preload.svg
+[downloads-url]: https://npmjs.org/package/node-preload
+[license-image]: https://img.shields.io/npm/l/node-preload.svg
diff --git a/node_modules/node-preload/generate-require.js b/node_modules/node-preload/generate-require.js
new file mode 100644
index 0000000000000..bd7cce081c6f2
--- /dev/null
+++ b/node_modules/node-preload/generate-require.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const path = require('path');
+
+const needsPathRegExp = /[\\ "]/;
+
+const needsPathEnv = dir => needsPathRegExp.test(dir);
+
+function generateRequire(filename) {
+	if (needsPathEnv(filename)) {
+		return `--require ${path.basename(filename)}`;
+	}
+
+	return `--require ${filename}`;
+}
+
+function processNodePath(value) {
+	const dir = path.dirname(require.resolve('./preload-path/node-preload.js'));
+	const existing = value === '' ? [] : value.split(path.delimiter);
+	if (existing.includes(dir)) {
+		return value;
+	}
+
+	return existing.concat(dir).join(path.delimiter);
+}
+
+module.exports = {
+	generateRequire,
+	processNodePath,
+	needsPathEnv
+};
diff --git a/node_modules/node-preload/hook-spawn.js b/node_modules/node-preload/hook-spawn.js
new file mode 100644
index 0000000000000..897ad6ae0de55
--- /dev/null
+++ b/node_modules/node-preload/hook-spawn.js
@@ -0,0 +1,21 @@
+'use strict';
+
+const path = require('path');
+
+const processOnSpawn = require('process-on-spawn');
+const {needsPathEnv, processNodePath} = require('./generate-require.js');
+const processNodeOptions = require('./process-node-options.js');
+const preloadList = require('./preload-list.js');
+const preloadListEnv = require('./preload-list-env.js');
+
+processOnSpawn.addListener(({env}) => {
+	env.NODE_OPTIONS = processNodeOptions(
+		env.NODE_OPTIONS || /* istanbul ignore next: impossible under nyc 15 */ ''
+	);
+	/* istanbul ignore next */
+	if (needsPathEnv(__dirname)) {
+		env.NODE_PATH = processNodePath(env.NODE_PATH || '');
+	}
+
+	env[preloadListEnv] = preloadList.join(path.delimiter);
+});
diff --git a/node_modules/node-preload/index.js b/node_modules/node-preload/index.js
new file mode 100644
index 0000000000000..3597259251107
--- /dev/null
+++ b/node_modules/node-preload/index.js
@@ -0,0 +1,5 @@
+'use strict';
+
+require('./hook-spawn.js');
+
+module.exports = require('./preload-list.js');
diff --git a/node_modules/node-preload/internal-preload-module.js b/node_modules/node-preload/internal-preload-module.js
new file mode 100644
index 0000000000000..efbd910c3f93a
--- /dev/null
+++ b/node_modules/node-preload/internal-preload-module.js
@@ -0,0 +1,25 @@
+'use strict';
+
+function findInternalPreloadModule() {
+	/* This song-and-dance is to keep esm happy. */
+	let mod = module;
+	const seen = new Set([mod]);
+	while ((mod = mod.parent)) {
+		/* Generally if we're being preloaded then
+		 * mod.parent.id should be 'internal/preload' */
+		/* istanbul ignore next: paranoia */
+		if (seen.has(mod)) {
+			return module;
+		}
+
+		seen.add(mod);
+		/* istanbul ignore next: this is hit but coverage cannot be collected */
+		if (mod.id === 'internal/preload') {
+			return mod;
+		}
+	}
+
+	return module;
+}
+
+module.exports = findInternalPreloadModule();
diff --git a/node_modules/node-preload/package.json b/node_modules/node-preload/package.json
new file mode 100644
index 0000000000000..93616213a2363
--- /dev/null
+++ b/node_modules/node-preload/package.json
@@ -0,0 +1,50 @@
+{
+	"name": "node-preload",
+	"version": "0.2.1",
+	"description": "Request that Node.js child processes preload modules",
+	"scripts": {
+		"release": "standard-version --sign",
+		"pretest": "xo",
+		"test": "nyc tape test/*.js"
+	},
+	"engines": {
+		"node": ">=8"
+	},
+	"main": "index.js",
+	"author": "Corey Farrell",
+	"license": "MIT",
+	"repository": {
+		"type": "git",
+		"url": "git+https://github.com/cfware/node-preload.git"
+	},
+	"bugs": {
+		"url": "https://github.com/cfware/node-preload/issues"
+	},
+	"homepage": "https://github.com/cfware/node-preload#readme",
+	"dependencies": {
+		"process-on-spawn": "^1.0.0"
+	},
+	"devDependencies": {
+		"esm": "^3.2.25",
+		"glob": "^7.1.6",
+		"nyc": "^15.0.0-beta.3",
+		"standard-version": "^7.0.0",
+		"tape": "^4.11.0",
+		"xo": "^0.25.3"
+	},
+	"xo": {
+		"rules": {
+			"import/no-unassigned-import": [
+				2,
+				{
+					"allow": [
+						"hook-spawn.js"
+					]
+				}
+			]
+		},
+		"ignores": [
+			"fixtures/esm.js"
+		]
+	}
+}
diff --git a/node_modules/node-preload/preload-list-env.js b/node_modules/node-preload/preload-list-env.js
new file mode 100644
index 0000000000000..459ce749fc800
--- /dev/null
+++ b/node_modules/node-preload/preload-list-env.js
@@ -0,0 +1,8 @@
+'use strict';
+
+const crypto = require('crypto');
+
+const hash = crypto.createHash('sha1');
+hash.update(__filename, 'utf8');
+
+module.exports = `NODE_PRELOAD_${hash.digest('hex')}`;
diff --git a/node_modules/node-preload/preload-list.js b/node_modules/node-preload/preload-list.js
new file mode 100644
index 0000000000000..cde3fa4c390e6
--- /dev/null
+++ b/node_modules/node-preload/preload-list.js
@@ -0,0 +1,15 @@
+'use strict';
+
+const path = require('path');
+const preloadListEnv = require('./preload-list-env.js');
+
+function getPreloadList() {
+	const env = process.env[preloadListEnv];
+	if (!env) {
+		return [];
+	}
+
+	return env.split(path.delimiter);
+}
+
+module.exports = getPreloadList();
diff --git a/node_modules/node-preload/preload-path/node-preload.js b/node_modules/node-preload/preload-path/node-preload.js
new file mode 100644
index 0000000000000..b99bc0703de41
--- /dev/null
+++ b/node_modules/node-preload/preload-path/node-preload.js
@@ -0,0 +1,11 @@
+'use strict';
+
+const internalPreloadModule = require('../internal-preload-module.js');
+const preloadList = require('../preload-list.js');
+
+require('../hook-spawn.js');
+
+preloadList.forEach(file => {
+	internalPreloadModule.require(file);
+});
+
diff --git a/node_modules/node-preload/process-node-options.js b/node_modules/node-preload/process-node-options.js
new file mode 100644
index 0000000000000..192b6ea735645
--- /dev/null
+++ b/node_modules/node-preload/process-node-options.js
@@ -0,0 +1,16 @@
+'use strict';
+
+const {generateRequire} = require('./generate-require.js');
+
+function processNodeOptions(value) {
+	const requireSelf = generateRequire(require.resolve('./preload-path/node-preload.js'));
+
+	/* istanbul ignore else */
+	if (!value.includes(requireSelf)) {
+		value = `${value} ${requireSelf}`;
+	}
+
+	return value;
+}
+
+module.exports = processNodeOptions;
diff --git a/node_modules/process-on-spawn/CHANGELOG.md b/node_modules/process-on-spawn/CHANGELOG.md
new file mode 100644
index 0000000000000..38843f8d4df4d
--- /dev/null
+++ b/node_modules/process-on-spawn/CHANGELOG.md
@@ -0,0 +1,10 @@
+# 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.
+
+## 1.0.0 (2019-12-16)
+
+
+### Features
+
+* Initial implementation ([39123b4](https://github.com/cfware/process-on-spawn/commit/39123b4ec06d8f9a22a0b19bbf955ab9e80fa376))
diff --git a/node_modules/process-on-spawn/LICENSE b/node_modules/process-on-spawn/LICENSE
new file mode 100644
index 0000000000000..807a18bdbcb7d
--- /dev/null
+++ b/node_modules/process-on-spawn/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 CFWare, LLC
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/process-on-spawn/README.md b/node_modules/process-on-spawn/README.md
new file mode 100644
index 0000000000000..ac3815e254af7
--- /dev/null
+++ b/node_modules/process-on-spawn/README.md
@@ -0,0 +1,64 @@
+# process-on-spawn
+
+[![Travis CI][travis-image]][travis-url]
+[![Greenkeeper badge][gk-image]](https://greenkeeper.io/)
+[![NPM Version][npm-image]][npm-url]
+[![NPM Downloads][downloads-image]][downloads-url]
+[![MIT][license-image]](LICENSE)
+
+Execute callbacks when child processes are spawned.
+
+## Usage
+
+```js
+'use strict';
+
+const processOnSpawn = require('process-on-spawn');
+processOnSpawn.addListener(opts => {
+  opts.env.CHILD_VARIABLE = 'value';
+});
+```
+
+### listener(opts)
+
+* `options` \<[Object]\>
+  * `execPath` \<[string]\> The command to run.
+  * `args` \<[string\[\]][string]\> Arguments of the child process.
+  * `cwd` \<[string]\> Current working directory of the child process.
+  * `detached` \<[boolean]\> The child will be prepared to run independently of its parent process.
+  * `uid` \<[number]\> The user identity to be used by the child.
+  * `gid` \<[number]\> The group identity to be used by the child.
+  * `windowsVerbatimArguments` \<[boolean]\> No quoting or escaping of arguments will be done on Windows.
+  * `windowsHide` \<[boolean]\> The subprocess console window that would normally be created on Windows systems will be hidden.
+
+All properties except `env` are read-only.
+
+### processOnSpawn.addListener(listener)
+
+Add a listener to be called after any listeners already attached.
+
+### processOnSpawn.prependListener(listener)
+
+Insert a listener to be called before any listeners already attached.
+
+### processOnSpawn.removeListener(listener)
+
+Remove the specified listener.  If the listener was added multiple times only
+the first is removed.
+
+### processOnSpawn.removeAllListeners()
+
+Remove all attached listeners.
+
+[npm-image]: https://img.shields.io/npm/v/process-on-spawn.svg
+[npm-url]: https://npmjs.org/package/process-on-spawn
+[travis-image]: https://travis-ci.org/cfware/process-on-spawn.svg?branch=master
+[travis-url]: https://travis-ci.org/cfware/process-on-spawn
+[gk-image]: https://badges.greenkeeper.io/cfware/process-on-spawn.svg
+[downloads-image]: https://img.shields.io/npm/dm/process-on-spawn.svg
+[downloads-url]: https://npmjs.org/package/process-on-spawn
+[license-image]: https://img.shields.io/npm/l/process-on-spawn.svg
+[Object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
+[string]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type
+[boolean]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type
+[number]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type
diff --git a/node_modules/process-on-spawn/index.js b/node_modules/process-on-spawn/index.js
new file mode 100644
index 0000000000000..b3d09918ffdde
--- /dev/null
+++ b/node_modules/process-on-spawn/index.js
@@ -0,0 +1,112 @@
+'use strict';
+
+/* Drop this dependency once node.js 12 is required. */
+const fromEntries = require('fromentries');
+
+const state = getState(1);
+
+function getState(version) {
+	const stateId = Symbol.for('process-on-spawn@*:singletonId');
+
+	/* istanbul ignore next: cannot cover this once nyc depends on this module */
+	if (stateId in global === false) {
+		/* Hopefully version and unwrap forward compatibility is never actually needed */
+		Object.defineProperty(global, stateId, {
+			writable: true,
+			value: {
+				version,
+				listeners: [],
+				unwrap: wrapSpawnFunctions()
+			}
+		});
+	}
+
+	return global[stateId];
+}
+
+function wrappedSpawnFunction(fn) {
+	return function (options) {
+		let env = fromEntries(
+			options.envPairs.map(nvp => nvp.split(/^([^=]*)=/).slice(1))
+		);
+
+		const opts = Object.create(null, {
+			env: {
+				enumerable: true,
+				get() {
+					return env;
+				},
+				set(value) {
+					if (!value || typeof value !== 'object') {
+						throw new TypeError('env must be an object');
+					}
+
+					env = value;
+				}
+			},
+			cwd: {
+				enumerable: true,
+				get() {
+					return options.cwd || process.cwd();
+				}
+			}
+		});
+
+		const args = [...options.args];
+		Object.freeze(args);
+		Object.assign(opts, {
+			execPath: options.file,
+			args,
+			detached: Boolean(options.detached),
+			uid: options.uid,
+			gid: options.gid,
+			windowsVerbatimArguments: Boolean(options.windowsVerbatimArguments),
+			windowsHide: Boolean(options.windowsHide)
+		});
+		Object.freeze(opts);
+
+		state.listeners.forEach(listener => {
+			listener(opts);
+		});
+
+		options.envPairs = Object.entries(opts.env).map(([name, value]) => `${name}=${value}`);
+
+		return fn.call(this, options);
+	};
+}
+
+function wrapSpawnFunctions() {
+	const {ChildProcess} = require('child_process');
+
+	/* eslint-disable-next-line node/no-deprecated-api */
+	const spawnSyncBinding = process.binding('spawn_sync');
+	const originalSync = spawnSyncBinding.spawn;
+	const originalAsync = ChildProcess.prototype.spawn;
+
+	spawnSyncBinding.spawn = wrappedSpawnFunction(spawnSyncBinding.spawn);
+	ChildProcess.prototype.spawn = wrappedSpawnFunction(ChildProcess.prototype.spawn);
+
+	/* istanbul ignore next: forward compatibility code */
+	return () => {
+		spawnSyncBinding.spawn = originalSync;
+		ChildProcess.prototype.spawn = originalAsync;
+	};
+}
+
+module.exports = {
+	addListener(listener) {
+		state.listeners.push(listener);
+	},
+	prependListener(listener) {
+		state.listeners.unshift(listener);
+	},
+	removeListener(listener) {
+		const idx = state.listeners.indexOf(listener);
+		if (idx !== -1) {
+			state.listeners.splice(idx, 1);
+		}
+	},
+	removeAllListeners() {
+		state.listeners = [];
+	}
+};
diff --git a/node_modules/process-on-spawn/package.json b/node_modules/process-on-spawn/package.json
new file mode 100644
index 0000000000000..9b7ac3865633b
--- /dev/null
+++ b/node_modules/process-on-spawn/package.json
@@ -0,0 +1,34 @@
+{
+	"name": "process-on-spawn",
+	"version": "1.0.0",
+	"description": "Execute callbacks when child processes are spawned",
+	"scripts": {
+		"release": "standard-version --sign",
+		"pretest": "xo",
+		"test": "nyc --silent tape test/*.js | tap-mocha-reporter classic",
+		"posttest": "nyc report --check-coverage"
+	},
+	"engines": {
+		"node": ">=8"
+	},
+	"author": "Corey Farrell",
+	"license": "MIT",
+	"repository": {
+		"type": "git",
+		"url": "git+https://github.com/cfware/process-on-spawn.git"
+	},
+	"bugs": {
+		"url": "https://github.com/cfware/process-on-spawn/issues"
+	},
+	"homepage": "https://github.com/cfware/process-on-spawn#readme",
+	"dependencies": {
+		"fromentries": "^1.2.0"
+	},
+	"devDependencies": {
+		"nyc": "^15.0.0-beta.3",
+		"standard-version": "^7.0.0",
+		"tap-mocha-reporter": "^5.0.0",
+		"tape": "^4.11.0",
+		"xo": "^0.25.3"
+	}
+}
diff --git a/package-lock.json b/package-lock.json
index 78a2be26cf7da..33a33a88a3f5f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -333,8 +333,7 @@
         "jsdom": "^16.5.2",
         "licensee": "^8.1.0",
         "marked-man": "^0.7.0",
-        "require-inject": "^1.4.4",
-        "tap": "^14.11.0",
+        "tap": "^15.0.2",
         "yaml": "^1.10.2"
       },
       "engines": {
@@ -440,9 +439,9 @@
       }
     },
     "node_modules/@babel/helper-module-transforms": {
-      "version": "7.13.12",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.12.tgz",
-      "integrity": "sha512-7zVQqMO3V+K4JOOj40kxiCrMf6xlQAkewBB0eu2b03OO/Q21ZutOzjpfD79A5gtE/2OWi1nv625MrDlGlkbknQ==",
+      "version": "7.13.14",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.14.tgz",
+      "integrity": "sha512-QuU/OJ0iAOSIatyVZmfqB0lbkVP0kDRiKj34xy+QNsnVZi/PA6BoSoreeqnxxa9EHFAIL0R9XOaAR/G9WlIy5g==",
       "dev": true,
       "dependencies": {
         "@babel/helper-module-imports": "^7.13.12",
@@ -451,8 +450,8 @@
         "@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.12"
+        "@babel/traverse": "^7.13.13",
+        "@babel/types": "^7.13.14"
       }
     },
     "node_modules/@babel/helper-optimise-call-expression": {
@@ -600,9 +599,9 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.13.12",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.12.tgz",
-      "integrity": "sha512-4T7Pb244rxH24yR116LAuJ+adxXXnHhZaLJjegJVKSdoNCe4x1eDBaud5YIcQFcqzsaD5BHvJw5BQ0AZapdCRw==",
+      "version": "7.13.15",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.15.tgz",
+      "integrity": "sha512-b9COtcAlVEQljy/9fbcMHpG+UIW9ReF+gpaxDHTlZd0c6/UU9ng8zdySAW9sRTzpvcdCHn6bUcbuYUgGzLAWVQ==",
       "dev": true,
       "bin": {
         "parser": "bin/babel-parser.js"
@@ -673,26 +672,25 @@
       }
     },
     "node_modules/@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==",
+      "version": "7.13.15",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.15.tgz",
+      "integrity": "sha512-/mpZMNvj6bce59Qzl09fHEs8Bt8NnpEDQYleHUPZQ3wXUMvXi+HJPLars68oAbmp839fGoOkv2pSL2z9ajCIaQ==",
       "dev": true,
       "dependencies": {
         "@babel/code-frame": "^7.12.13",
-        "@babel/generator": "^7.13.0",
+        "@babel/generator": "^7.13.9",
         "@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",
+        "@babel/parser": "^7.13.15",
+        "@babel/types": "^7.13.14",
         "debug": "^4.1.0",
-        "globals": "^11.1.0",
-        "lodash": "^4.17.19"
+        "globals": "^11.1.0"
       }
     },
     "node_modules/@babel/types": {
-      "version": "7.13.12",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.12.tgz",
-      "integrity": "sha512-K4nY2xFN4QMvQwkQ+zmBDp6ANMbVNw6BbxWmYA4qNjhR9W+Lj/8ky5MEY2Me5r+B2c6/v6F53oMndG+f9s3IiA==",
+      "version": "7.13.14",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz",
+      "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==",
       "dev": true,
       "dependencies": {
         "@babel/helper-validator-identifier": "^7.12.11",
@@ -741,6 +739,110 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/@istanbuljs/load-nyc-config": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+      "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+      "dev": true,
+      "dependencies": {
+        "camelcase": "^5.3.1",
+        "find-up": "^4.1.0",
+        "get-package-type": "^0.1.0",
+        "js-yaml": "^3.13.1",
+        "resolve-from": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dev": true,
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@istanbuljs/schema": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+      "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/@mdx-js/mdx": {
       "version": "1.6.22",
       "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz",
@@ -1157,9 +1259,9 @@
       "inBundle": true
     },
     "node_modules/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,
       "dependencies": {
         "normalize-path": "^3.0.0",
@@ -1170,15 +1272,15 @@
       }
     },
     "node_modules/append-transform": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz",
-      "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz",
+      "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==",
       "dev": true,
       "dependencies": {
-        "default-require-extensions": "^2.0.0"
+        "default-require-extensions": "^3.0.0"
       },
       "engines": {
-        "node": ">=4"
+        "node": ">=8"
       }
     },
     "node_modules/aproba": {
@@ -1203,12 +1305,6 @@
         "readable-stream": "^2.0.6"
       }
     },
-    "node_modules/arg": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
-      "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
-      "dev": true
-    },
     "node_modules/argparse": {
       "version": "1.0.10",
       "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@@ -1297,12 +1393,12 @@
       }
     },
     "node_modules/async-hook-domain": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/async-hook-domain/-/async-hook-domain-1.1.3.tgz",
-      "integrity": "sha512-ZovMxSbADV3+biB7oR1GL5lGyptI24alp0LWHlmz1OFc5oL47pz3EiIF6nXOkDW7yLqih4NtsiYduzdDW0i+Wg==",
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/async-hook-domain/-/async-hook-domain-2.0.3.tgz",
+      "integrity": "sha512-MadiLLDEZRZzZwcm0dgS+K99qXZ4H2saAUwUgwzFulbAkXrKi3AX5FvWS3FFTQtLMwrqcGqAJe6o12KrObejQA==",
       "dev": true,
-      "dependencies": {
-        "source-map-support": "^0.5.11"
+      "engines": {
+        "node": ">=10"
       }
     },
     "node_modules/asynckit": {
@@ -1379,9 +1475,9 @@
       }
     },
     "node_modules/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==",
       "inBundle": true
     },
     "node_modules/base64-js": {
@@ -1440,9 +1536,9 @@
       }
     },
     "node_modules/bind-obj-methods": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/bind-obj-methods/-/bind-obj-methods-2.0.1.tgz",
-      "integrity": "sha512-kKzUyCuc+jsWH4C2nW5KB2nh+rQRbQcdphfo9UN3j1uwIFGZ3JB8njtRZOiUAQCkxazH0nDQPN6x/zhvFcbZIw==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/bind-obj-methods/-/bind-obj-methods-3.0.0.tgz",
+      "integrity": "sha512-nLEaaz3/sEzNSyPWRsN9HNsqwk1AUyECtGj+XwGdIi3xABnEqecvXtIJ0wehQXuuER5uZ/5fTs2usONgYjG+iw==",
       "dev": true,
       "engines": {
         "node": ">=10"
@@ -1584,29 +1680,18 @@
       }
     },
     "node_modules/caching-transform": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz",
-      "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz",
+      "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==",
       "dev": true,
       "dependencies": {
-        "hasha": "^3.0.0",
-        "make-dir": "^2.0.0",
-        "package-hash": "^3.0.0",
-        "write-file-atomic": "^2.4.2"
+        "hasha": "^5.0.0",
+        "make-dir": "^3.0.0",
+        "package-hash": "^4.0.0",
+        "write-file-atomic": "^3.0.0"
       },
       "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/caching-transform/node_modules/write-file-atomic": {
-      "version": "2.4.3",
-      "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
-      "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
-      "dev": true,
-      "dependencies": {
-        "graceful-fs": "^4.1.11",
-        "imurmurhash": "^0.1.4",
-        "signal-exit": "^3.0.2"
+        "node": ">=8"
       }
     },
     "node_modules/call-bind": {
@@ -1622,12 +1707,6 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
-    "node_modules/caller": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/caller/-/caller-1.0.1.tgz",
-      "integrity": "sha1-uFGGD3Dhlds9J3OVqhp+I+ow7PU=",
-      "dev": true
-    },
     "node_modules/callsites": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -2073,31 +2152,6 @@
         "node": ">=6"
       }
     },
-    "node_modules/cp-file": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz",
-      "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==",
-      "dev": true,
-      "dependencies": {
-        "graceful-fs": "^4.1.2",
-        "make-dir": "^2.0.0",
-        "nested-error-stacks": "^2.0.0",
-        "pify": "^4.0.1",
-        "safe-buffer": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/cp-file/node_modules/pify": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
-      "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/cross-spawn": {
       "version": "7.0.3",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -2237,15 +2291,24 @@
       "dev": true
     },
     "node_modules/default-require-extensions": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz",
-      "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz",
+      "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==",
       "dev": true,
       "dependencies": {
-        "strip-bom": "^3.0.0"
+        "strip-bom": "^4.0.0"
       },
       "engines": {
-        "node": ">=4"
+        "node": ">=8"
+      }
+    },
+    "node_modules/default-require-extensions/node_modules/strip-bom": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+      "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
       }
     },
     "node_modules/defaults": {
@@ -2337,15 +2400,6 @@
         "node": ">=0.3.1"
       }
     },
-    "node_modules/diff-frag": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/diff-frag/-/diff-frag-1.0.1.tgz",
-      "integrity": "sha512-6/v2PC/6UTGcWPPetb9acL8foberUg/CtPdALeJUdD1B/weHNvzftoo00gYznqHGRhHEbykUGzqfG9RWOSr5yw==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
     "node_modules/docopt": {
       "version": "0.6.2",
       "resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz",
@@ -2614,9 +2668,9 @@
       }
     },
     "node_modules/eslint": {
-      "version": "7.23.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.23.0.tgz",
-      "integrity": "sha512-kqvNVbdkjzpFy0XOszNwjkKzZ+6TcwCQ/h+ozlcIWwaimBBuhlQ4nN6kbiM2L+OjDcznkTJxzYfRFH92sx4a0Q==",
+      "version": "7.24.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz",
+      "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==",
       "dev": true,
       "dependencies": {
         "@babel/code-frame": "7.12.11",
@@ -2930,9 +2984,9 @@
       }
     },
     "node_modules/eslint/node_modules/globals": {
-      "version": "13.7.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-13.7.0.tgz",
-      "integrity": "sha512-Aipsz6ZKRxa/xQkZhNg0qIWXT6x6rD46f6x/PCnBomlttdIyAPak4YD9jTmKpZ72uROSMU87qJtcgpgHaVchiA==",
+      "version": "13.8.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz",
+      "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==",
       "dev": true,
       "dependencies": {
         "type-fest": "^0.20.2"
@@ -2968,15 +3022,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/esm": {
-      "version": "3.2.25",
-      "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
-      "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/espree": {
       "version": "7.3.1",
       "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
@@ -3152,42 +3197,45 @@
       }
     },
     "node_modules/find-cache-dir": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
-      "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz",
+      "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==",
       "dev": true,
       "dependencies": {
         "commondir": "^1.0.1",
-        "make-dir": "^2.0.0",
-        "pkg-dir": "^3.0.0"
+        "make-dir": "^3.0.2",
+        "pkg-dir": "^4.1.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/avajs/find-cache-dir?sponsor=1"
       }
     },
     "node_modules/find-cache-dir/node_modules/find-up": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
-      "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
       "dev": true,
       "dependencies": {
-        "locate-path": "^3.0.0"
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/find-cache-dir/node_modules/locate-path": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
-      "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
       "dev": true,
       "dependencies": {
-        "p-locate": "^3.0.0",
-        "path-exists": "^3.0.0"
+        "p-locate": "^4.1.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/find-cache-dir/node_modules/p-limit": {
@@ -3206,15 +3254,15 @@
       }
     },
     "node_modules/find-cache-dir/node_modules/p-locate": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
-      "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
       "dev": true,
       "dependencies": {
-        "p-limit": "^2.0.0"
+        "p-limit": "^2.2.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/find-cache-dir/node_modules/p-try": {
@@ -3226,16 +3274,25 @@
         "node": ">=6"
       }
     },
+    "node_modules/find-cache-dir/node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/find-cache-dir/node_modules/pkg-dir": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
-      "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+      "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
       "dev": true,
       "dependencies": {
-        "find-up": "^3.0.0"
+        "find-up": "^4.0.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/find-up": {
@@ -3275,81 +3332,19 @@
       "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
       "dev": true
     },
-    "node_modules/flow-parser": {
-      "version": "0.147.0",
-      "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.147.0.tgz",
-      "integrity": "sha512-z+b/pgp2QLvsWJkzhKXU8yC5TmaNyXGRmHac3x0Swmn9uQESRXhNIJq9TPHKPPeWgFym33OLO+5BlIdy/tXRCQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
-    "node_modules/flow-remove-types": {
-      "version": "2.147.0",
-      "resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.147.0.tgz",
-      "integrity": "sha512-ppZdtui3daAhBe0dkghBdtdIdSRbc/p/IEXw3t6vtlbS2KNpY8G3cu5RupXT3pGvFQbbXHP7mwNCEKSEYGU6Aw==",
-      "dev": true,
-      "dependencies": {
-        "flow-parser": "^0.147.0",
-        "pirates": "^3.0.2",
-        "vlq": "^0.2.1"
-      },
-      "bin": {
-        "flow-node": "flow-node",
-        "flow-remove-types": "flow-remove-types"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
     "node_modules/foreground-child": {
-      "version": "1.5.6",
-      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz",
-      "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=",
-      "dev": true,
-      "dependencies": {
-        "cross-spawn": "^4",
-        "signal-exit": "^3.0.0"
-      }
-    },
-    "node_modules/foreground-child/node_modules/cross-spawn": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz",
-      "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=",
-      "dev": true,
-      "dependencies": {
-        "lru-cache": "^4.0.1",
-        "which": "^1.2.9"
-      }
-    },
-    "node_modules/foreground-child/node_modules/lru-cache": {
-      "version": "4.1.5",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
-      "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
-      "dev": true,
-      "dependencies": {
-        "pseudomap": "^1.0.2",
-        "yallist": "^2.1.2"
-      }
-    },
-    "node_modules/foreground-child/node_modules/which": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
+      "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==",
       "dev": true,
       "dependencies": {
-        "isexe": "^2.0.0"
+        "cross-spawn": "^7.0.0",
+        "signal-exit": "^3.0.2"
       },
-      "bin": {
-        "which": "bin/which"
+      "engines": {
+        "node": ">=8.0.0"
       }
     },
-    "node_modules/foreground-child/node_modules/yallist": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
-      "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
-      "dev": true
-    },
     "node_modules/forever-agent": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
@@ -3373,6 +3368,26 @@
         "node": ">= 0.12"
       }
     },
+    "node_modules/fromentries": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz",
+      "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
     "node_modules/fs-access": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-2.0.0.tgz",
@@ -3437,9 +3452,9 @@
       "inBundle": true
     },
     "node_modules/function-loop": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/function-loop/-/function-loop-1.0.2.tgz",
-      "integrity": "sha512-Iw4MzMfS3udk/rqxTiDDCllhGwlOrsr50zViTOO/W6lS/9y6B1J0BD2VZzrnWUYBJsl3aeqjgR5v7bWWhZSYbA==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/function-loop/-/function-loop-2.0.1.tgz",
+      "integrity": "sha512-ktIR+O6i/4h+j/ZhZJNdzeI4i9lEPeEK6UPR2EVyTVBqOwcU3Za9xYKLH64ZR9HmcROyRrOkizNyjjtWJzDDkQ==",
       "dev": true
     },
     "node_modules/functional-red-black-tree": {
@@ -3528,6 +3543,15 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/get-package-type": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+      "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
     "node_modules/getpass": {
       "version": "0.1.7",
       "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
@@ -3662,15 +3686,19 @@
       "inBundle": true
     },
     "node_modules/hasha": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz",
-      "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=",
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
+      "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==",
       "dev": true,
       "dependencies": {
-        "is-stream": "^1.0.1"
+        "is-stream": "^2.0.0",
+        "type-fest": "^0.8.0"
       },
       "engines": {
-        "node": ">=4"
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
     "node_modules/hast-to-hyperscript": {
@@ -4265,9 +4293,9 @@
       }
     },
     "node_modules/is-potential-custom-element-name": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz",
-      "integrity": "sha1-DFLlS8yjkbssSUsh6GJtczbG45c=",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+      "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
       "dev": true
     },
     "node_modules/is-regex": {
@@ -4287,12 +4315,12 @@
       }
     },
     "node_modules/is-stream": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
-      "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+      "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,
       "engines": {
-        "node": ">=0.10.0"
+        "node": ">=8"
       }
     },
     "node_modules/is-string": {
@@ -4338,10 +4366,19 @@
         "url": "https://github.com/sponsors/wooorm"
       }
     },
-    "node_modules/is-word-character": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz",
-      "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==",
+    "node_modules/is-windows": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+      "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-word-character": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz",
+      "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==",
       "dev": true,
       "funding": {
         "type": "github",
@@ -4367,42 +4404,39 @@
       "inBundle": true
     },
     "node_modules/istanbul-lib-coverage": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
-      "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz",
+      "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==",
       "dev": true,
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/istanbul-lib-hook": {
-      "version": "2.0.7",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz",
-      "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz",
+      "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==",
       "dev": true,
       "dependencies": {
-        "append-transform": "^1.0.0"
+        "append-transform": "^2.0.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/istanbul-lib-instrument": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
-      "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
+      "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
       "dev": true,
       "dependencies": {
-        "@babel/generator": "^7.4.0",
-        "@babel/parser": "^7.4.3",
-        "@babel/template": "^7.4.0",
-        "@babel/traverse": "^7.4.3",
-        "@babel/types": "^7.4.0",
-        "istanbul-lib-coverage": "^2.0.5",
-        "semver": "^6.0.0"
+        "@babel/core": "^7.7.5",
+        "@istanbuljs/schema": "^0.1.2",
+        "istanbul-lib-coverage": "^3.0.0",
+        "semver": "^6.3.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/istanbul-lib-instrument/node_modules/semver": {
@@ -4415,158 +4449,61 @@
       }
     },
     "node_modules/istanbul-lib-processinfo": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-1.0.0.tgz",
-      "integrity": "sha512-FY0cPmWa4WoQNlvB8VOcafiRoB5nB+l2Pz2xGuXHRSy1KM8QFOYfz/rN+bGMCAeejrY3mrpF5oJHcN0s/garCg==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz",
+      "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==",
       "dev": true,
       "dependencies": {
         "archy": "^1.0.0",
-        "cross-spawn": "^6.0.5",
-        "istanbul-lib-coverage": "^2.0.3",
-        "rimraf": "^2.6.3",
-        "uuid": "^3.3.2"
-      }
-    },
-    "node_modules/istanbul-lib-processinfo/node_modules/cross-spawn": {
-      "version": "6.0.5",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
-      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
-      "dev": true,
-      "dependencies": {
-        "nice-try": "^1.0.4",
-        "path-key": "^2.0.1",
-        "semver": "^5.5.0",
-        "shebang-command": "^1.2.0",
-        "which": "^1.2.9"
+        "cross-spawn": "^7.0.0",
+        "istanbul-lib-coverage": "^3.0.0-alpha.1",
+        "make-dir": "^3.0.0",
+        "p-map": "^3.0.0",
+        "rimraf": "^3.0.0",
+        "uuid": "^3.3.3"
       },
       "engines": {
-        "node": ">=4.8"
-      }
-    },
-    "node_modules/istanbul-lib-processinfo/node_modules/path-key": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
-      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/istanbul-lib-processinfo/node_modules/rimraf": {
-      "version": "2.7.1",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-      "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-      "dev": true,
-      "dependencies": {
-        "glob": "^7.1.3"
-      },
-      "bin": {
-        "rimraf": "bin.js"
-      }
-    },
-    "node_modules/istanbul-lib-processinfo/node_modules/semver": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver"
+        "node": ">=8"
       }
     },
-    "node_modules/istanbul-lib-processinfo/node_modules/shebang-command": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
-      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+    "node_modules/istanbul-lib-processinfo/node_modules/p-map": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
+      "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==",
       "dev": true,
       "dependencies": {
-        "shebang-regex": "^1.0.0"
+        "aggregate-error": "^3.0.0"
       },
       "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/istanbul-lib-processinfo/node_modules/shebang-regex": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
-      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/istanbul-lib-processinfo/node_modules/which": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
-      "dev": true,
-      "dependencies": {
-        "isexe": "^2.0.0"
-      },
-      "bin": {
-        "which": "bin/which"
+        "node": ">=8"
       }
     },
     "node_modules/istanbul-lib-report": {
-      "version": "2.0.8",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz",
-      "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==",
-      "dev": true,
-      "dependencies": {
-        "istanbul-lib-coverage": "^2.0.5",
-        "make-dir": "^2.1.0",
-        "supports-color": "^6.1.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/istanbul-lib-report/node_modules/has-flag": {
       "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/istanbul-lib-report/node_modules/supports-color": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
-      "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
+      "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
       "dev": true,
       "dependencies": {
-        "has-flag": "^3.0.0"
+        "istanbul-lib-coverage": "^3.0.0",
+        "make-dir": "^3.0.0",
+        "supports-color": "^7.1.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/istanbul-lib-source-maps": {
-      "version": "3.0.6",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz",
-      "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz",
+      "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==",
       "dev": true,
       "dependencies": {
         "debug": "^4.1.1",
-        "istanbul-lib-coverage": "^2.0.5",
-        "make-dir": "^2.1.0",
-        "rimraf": "^2.6.3",
+        "istanbul-lib-coverage": "^3.0.0",
         "source-map": "^0.6.1"
       },
       "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/istanbul-lib-source-maps/node_modules/rimraf": {
-      "version": "2.7.1",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-      "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-      "dev": true,
-      "dependencies": {
-        "glob": "^7.1.3"
-      },
-      "bin": {
-        "rimraf": "bin.js"
+        "node": ">=8"
       }
     },
     "node_modules/istanbul-lib-source-maps/node_modules/source-map": {
@@ -4579,15 +4516,16 @@
       }
     },
     "node_modules/istanbul-reports": {
-      "version": "2.2.7",
-      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz",
-      "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==",
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz",
+      "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==",
       "dev": true,
       "dependencies": {
-        "html-escaper": "^2.0.0"
+        "html-escaper": "^2.0.0",
+        "istanbul-lib-report": "^3.0.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/jackspeak": {
@@ -4628,9 +4566,9 @@
       "inBundle": true
     },
     "node_modules/jsdom": {
-      "version": "16.5.2",
-      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.5.2.tgz",
-      "integrity": "sha512-JxNtPt9C1ut85boCbJmffaQ06NBnzkQY/MWO3YxPW8IWS38A26z+B1oBvA9LwKrytewdfymnhi4UNH3/RAgZrg==",
+      "version": "16.5.3",
+      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.5.3.tgz",
+      "integrity": "sha512-Qj1H+PEvUsOtdPJ056ewXM4UJPCi4hhLA8wpiz9F2YvsRBhuFsXxtrIFAgGBDynQA9isAMGE91PfUYbdMPXuTA==",
       "dev": true,
       "dependencies": {
         "abab": "^2.0.5",
@@ -4673,9 +4611,9 @@
       }
     },
     "node_modules/jsdom/node_modules/acorn": {
-      "version": "8.1.0",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.1.0.tgz",
-      "integrity": "sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA==",
+      "version": "8.1.1",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.1.1.tgz",
+      "integrity": "sha512-xYiIVjNuqtKXMxlRMDc6mZUhXehod4a3gbZ1qRlM7icK4EbxUFNLhWoPblCvFtB2Y9CIqHP3CF/rdxLItaQv8g==",
       "dev": true,
       "bin": {
         "acorn": "bin/acorn"
@@ -4696,12 +4634,6 @@
         "node": ">=4"
       }
     },
-    "node_modules/json-parse-better-errors": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
-      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
-      "dev": true
-    },
     "node_modules/json-parse-errback": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/json-parse-errback/-/json-parse-errback-2.0.1.tgz",
@@ -4787,9 +4719,9 @@
       }
     },
     "node_modules/just-diff": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-3.0.2.tgz",
-      "integrity": "sha512-+EiNvacECnZbszZa5IMjzrJ3dy2HKMXyGaNYWBnXy+iWW+437jIvQUrWaM9M+XI/6gOH8EjqvhGUOSh7ETekyg==",
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-3.1.1.tgz",
+      "integrity": "sha512-sdMWKjRq8qWZEjDcVA6llnUT8RDEBIfOiGpYFPYa9u+2c39JCsejktSP7mj5eRid5EIvTzIpQ2kDOCw1Nq9BjQ==",
       "inBundle": true
     },
     "node_modules/just-diff-apply": {
@@ -4966,6 +4898,43 @@
         "stringify-package": "^1.0.1"
       }
     },
+    "node_modules/libtap": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/libtap/-/libtap-1.1.1.tgz",
+      "integrity": "sha512-Fye8fh1+G7E8qqmjQaY+pXGxy7HM0S6bqCCJFLa16+g2jODBByxbJFDpjbDNF69wfRVyvJ+foLZc1WTIv7dx+g==",
+      "dev": true,
+      "dependencies": {
+        "async-hook-domain": "^2.0.1",
+        "bind-obj-methods": "^3.0.0",
+        "diff": "^4.0.2",
+        "function-loop": "^2.0.1",
+        "minipass": "^3.1.1",
+        "own-or": "^1.0.0",
+        "own-or-env": "^1.0.1",
+        "signal-exit": "^3.0.2",
+        "stack-utils": "^2.0.1",
+        "tap-parser": "^10.0.1",
+        "tap-yaml": "^1.0.0",
+        "tcompare": "^5.0.1",
+        "trivial-deferred": "^1.0.1",
+        "yapool": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/libtap/node_modules/diff": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.3.1"
+      }
+    },
     "node_modules/licensee": {
       "version": "8.2.0",
       "resolved": "https://registry.npmjs.org/licensee/-/licensee-8.2.0.tgz",
@@ -5035,12 +5004,30 @@
       "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
       "dev": true
     },
+    "node_modules/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
+    },
+    "node_modules/lodash.flatten": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+      "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
+      "dev": true
+    },
     "node_modules/lodash.flattendeep": {
       "version": "4.4.0",
       "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
       "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
       "dev": true
     },
+    "node_modules/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
+    },
     "node_modules/lodash.uniq": {
       "version": "4.5.0",
       "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@@ -5081,42 +5068,29 @@
       }
     },
     "node_modules/make-dir": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
-      "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+      "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
       "dev": true,
       "dependencies": {
-        "pify": "^4.0.1",
-        "semver": "^5.6.0"
+        "semver": "^6.0.0"
       },
       "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/make-dir/node_modules/pify": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
-      "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
     "node_modules/make-dir/node_modules/semver": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
       "dev": true,
       "bin": {
-        "semver": "bin/semver"
+        "semver": "bin/semver.js"
       }
     },
-    "node_modules/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
-    },
     "node_modules/make-fetch-happen": {
       "version": "8.0.14",
       "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz",
@@ -5230,40 +5204,22 @@
       "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
       "dev": true
     },
-    "node_modules/merge-source-map": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz",
-      "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==",
-      "dev": true,
-      "dependencies": {
-        "source-map": "^0.6.1"
-      }
-    },
-    "node_modules/merge-source-map/node_modules/source-map": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/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.47.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz",
+      "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==",
       "inBundle": true,
       "engines": {
         "node": ">= 0.6"
       }
     },
     "node_modules/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==",
+      "version": "2.1.30",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz",
+      "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==",
       "inBundle": true,
       "dependencies": {
-        "mime-db": "1.46.0"
+        "mime-db": "1.47.0"
       },
       "engines": {
         "node": ">= 0.6"
@@ -5455,18 +5411,6 @@
       "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
       "dev": true
     },
-    "node_modules/nested-error-stacks": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz",
-      "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==",
-      "dev": true
-    },
-    "node_modules/nice-try": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
-      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
-      "dev": true
-    },
     "node_modules/node-abi": {
       "version": "2.21.0",
       "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.21.0.tgz",
@@ -5515,13 +5459,16 @@
         "node": ">= 10.12.0"
       }
     },
-    "node_modules/node-modules-regexp": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz",
-      "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=",
+    "node_modules/node-preload": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
+      "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==",
       "dev": true,
+      "dependencies": {
+        "process-on-spawn": "^1.0.0"
+      },
       "engines": {
-        "node": ">=0.10.0"
+        "node": ">=8"
       }
     },
     "node_modules/noop-logger": {
@@ -5732,67 +5679,69 @@
       "dev": true
     },
     "node_modules/nyc": {
-      "version": "14.1.1",
-      "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz",
-      "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==",
+      "version": "15.1.0",
+      "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz",
+      "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==",
       "dev": true,
       "dependencies": {
-        "archy": "^1.0.0",
-        "caching-transform": "^3.0.2",
-        "convert-source-map": "^1.6.0",
-        "cp-file": "^6.2.0",
-        "find-cache-dir": "^2.1.0",
-        "find-up": "^3.0.0",
-        "foreground-child": "^1.5.6",
-        "glob": "^7.1.3",
-        "istanbul-lib-coverage": "^2.0.5",
-        "istanbul-lib-hook": "^2.0.7",
-        "istanbul-lib-instrument": "^3.3.0",
-        "istanbul-lib-report": "^2.0.8",
-        "istanbul-lib-source-maps": "^3.0.6",
-        "istanbul-reports": "^2.2.4",
-        "js-yaml": "^3.13.1",
-        "make-dir": "^2.1.0",
-        "merge-source-map": "^1.1.0",
-        "resolve-from": "^4.0.0",
-        "rimraf": "^2.6.3",
+        "@istanbuljs/load-nyc-config": "^1.0.0",
+        "@istanbuljs/schema": "^0.1.2",
+        "caching-transform": "^4.0.0",
+        "convert-source-map": "^1.7.0",
+        "decamelize": "^1.2.0",
+        "find-cache-dir": "^3.2.0",
+        "find-up": "^4.1.0",
+        "foreground-child": "^2.0.0",
+        "get-package-type": "^0.1.0",
+        "glob": "^7.1.6",
+        "istanbul-lib-coverage": "^3.0.0",
+        "istanbul-lib-hook": "^3.0.0",
+        "istanbul-lib-instrument": "^4.0.0",
+        "istanbul-lib-processinfo": "^2.0.2",
+        "istanbul-lib-report": "^3.0.0",
+        "istanbul-lib-source-maps": "^4.0.0",
+        "istanbul-reports": "^3.0.2",
+        "make-dir": "^3.0.0",
+        "node-preload": "^0.2.1",
+        "p-map": "^3.0.0",
+        "process-on-spawn": "^1.0.0",
+        "resolve-from": "^5.0.0",
+        "rimraf": "^3.0.0",
         "signal-exit": "^3.0.2",
-        "spawn-wrap": "^1.4.2",
-        "test-exclude": "^5.2.3",
-        "uuid": "^3.3.2",
-        "yargs": "^13.2.2",
-        "yargs-parser": "^13.0.0"
+        "spawn-wrap": "^2.0.0",
+        "test-exclude": "^6.0.0",
+        "yargs": "^15.0.2"
       },
       "bin": {
         "nyc": "bin/nyc.js"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8.9"
       }
     },
     "node_modules/nyc/node_modules/find-up": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
-      "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
       "dev": true,
       "dependencies": {
-        "locate-path": "^3.0.0"
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/nyc/node_modules/locate-path": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
-      "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
       "dev": true,
       "dependencies": {
-        "p-locate": "^3.0.0",
-        "path-exists": "^3.0.0"
+        "p-locate": "^4.1.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/nyc/node_modules/p-limit": {
@@ -5811,15 +5760,27 @@
       }
     },
     "node_modules/nyc/node_modules/p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/nyc/node_modules/p-map": {
       "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
-      "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
+      "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==",
       "dev": true,
       "dependencies": {
-        "p-limit": "^2.0.0"
+        "aggregate-error": "^3.0.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/nyc/node_modules/p-try": {
@@ -5831,16 +5792,22 @@
         "node": ">=6"
       }
     },
-    "node_modules/nyc/node_modules/rimraf": {
-      "version": "2.7.1",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-      "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+    "node_modules/nyc/node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
       "dev": true,
-      "dependencies": {
-        "glob": "^7.1.3"
-      },
-      "bin": {
-        "rimraf": "bin.js"
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/nyc/node_modules/resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
       }
     },
     "node_modules/oauth-sign": {
@@ -5967,15 +5934,6 @@
         "node": ">= 0.8.0"
       }
     },
-    "node_modules/os-homedir": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
-      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/own-or": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/own-or/-/own-or-1.0.0.tgz",
@@ -6040,18 +5998,18 @@
       }
     },
     "node_modules/package-hash": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz",
-      "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz",
+      "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==",
       "dev": true,
       "dependencies": {
         "graceful-fs": "^4.1.15",
-        "hasha": "^3.0.0",
+        "hasha": "^5.0.0",
         "lodash.flattendeep": "^4.4.0",
         "release-zalgo": "^1.0.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/pacote": {
@@ -6198,9 +6156,9 @@
       "inBundle": true
     },
     "node_modules/picomatch": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
-      "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz",
+      "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==",
       "dev": true,
       "engines": {
         "node": ">=8.6"
@@ -6218,18 +6176,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/pirates": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/pirates/-/pirates-3.0.2.tgz",
-      "integrity": "sha512-c5CgUJq6H2k6MJz72Ak1F5sN9n9wlSlJyEnwvpm9/y3WB4E3pHBDT2c6PEiS1vyJvq2bUxUAIu0EGf8Cx4Ic7Q==",
-      "dev": true,
-      "dependencies": {
-        "node-modules-regexp": "^1.0.0"
-      },
-      "engines": {
-        "node": ">= 4"
-      }
-    },
     "node_modules/pkg-dir": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
@@ -6243,9 +6189,9 @@
       }
     },
     "node_modules/prebuild-install": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.0.1.tgz",
-      "integrity": "sha512-7GOJrLuow8yeiyv75rmvZyeMGzl8mdEX5gY69d6a6bHWmiPevwqFw+tQavhK0EYMaSg3/KD24cWqeQv1EWsqDQ==",
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.1.tgz",
+      "integrity": "sha512-M+cKwofFlHa5VpTWub7GLg5RLcunYIcLqtY5pKcls/u7xaAb8FrXZ520qY8rkpYy5xw90tYCyMO0MP5ggzR3Sw==",
       "dev": true,
       "dependencies": {
         "detect-libc": "^1.0.3",
@@ -6254,15 +6200,14 @@
         "minimist": "^1.2.3",
         "mkdirp-classic": "^0.5.3",
         "napi-build-utils": "^1.0.1",
-        "node-abi": "^2.7.0",
+        "node-abi": "^2.21.0",
         "noop-logger": "^0.1.1",
         "npmlog": "^4.0.1",
         "pump": "^3.0.0",
         "rc": "^1.2.7",
         "simple-get": "^3.0.3",
         "tar-fs": "^2.0.0",
-        "tunnel-agent": "^0.6.0",
-        "which-pm-runs": "^1.0.0"
+        "tunnel-agent": "^0.6.0"
       },
       "bin": {
         "prebuild-install": "bin.js"
@@ -6286,6 +6231,18 @@
       "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
       "inBundle": true
     },
+    "node_modules/process-on-spawn": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz",
+      "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==",
+      "dev": true,
+      "dependencies": {
+        "fromentries": "^1.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/progress": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
@@ -6365,12 +6322,6 @@
         "url": "https://github.com/sponsors/wooorm"
       }
     },
-    "node_modules/pseudomap": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
-      "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
-      "dev": true
-    },
     "node_modules/psl": {
       "version": "1.8.0",
       "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
@@ -6542,9 +6493,9 @@
       }
     },
     "node_modules/read-package-tree/node_modules/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
     },
     "node_modules/read-package-tree/node_modules/normalize-package-data": {
@@ -6608,9 +6559,9 @@
       }
     },
     "node_modules/read-pkg/node_modules/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
     },
     "node_modules/read-pkg/node_modules/normalize-package-data": {
@@ -6892,15 +6843,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/require-inject": {
-      "version": "1.4.4",
-      "resolved": "https://registry.npmjs.org/require-inject/-/require-inject-1.4.4.tgz",
-      "integrity": "sha512-5Y5ctRN84+I4iOZO61gm+48tgP/6Hcd3VZydkaEM3MCuOvnHRsTJYQBOc01faI/Z9at5nsCAJVHhlfPA6Pc0Og==",
-      "dev": true,
-      "dependencies": {
-        "caller": "^1.0.1"
-      }
-    },
     "node_modules/require-main-filename": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
@@ -7182,53 +7124,20 @@
       }
     },
     "node_modules/spawn-wrap": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz",
-      "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz",
+      "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==",
       "dev": true,
       "dependencies": {
-        "foreground-child": "^1.5.6",
-        "mkdirp": "^0.5.0",
-        "os-homedir": "^1.0.1",
-        "rimraf": "^2.6.2",
+        "foreground-child": "^2.0.0",
+        "is-windows": "^1.0.2",
+        "make-dir": "^3.0.0",
+        "rimraf": "^3.0.0",
         "signal-exit": "^3.0.2",
-        "which": "^1.3.0"
-      }
-    },
-    "node_modules/spawn-wrap/node_modules/mkdirp": {
-      "version": "0.5.5",
-      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
-      "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
-      "dev": true,
-      "dependencies": {
-        "minimist": "^1.2.5"
-      },
-      "bin": {
-        "mkdirp": "bin/cmd.js"
-      }
-    },
-    "node_modules/spawn-wrap/node_modules/rimraf": {
-      "version": "2.7.1",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-      "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-      "dev": true,
-      "dependencies": {
-        "glob": "^7.1.3"
-      },
-      "bin": {
-        "rimraf": "bin.js"
-      }
-    },
-    "node_modules/spawn-wrap/node_modules/which": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
-      "dev": true,
-      "dependencies": {
-        "isexe": "^2.0.0"
+        "which": "^2.0.1"
       },
-      "bin": {
-        "which": "bin/which"
+      "engines": {
+        "node": ">=8"
       }
     },
     "node_modules/spdx-compare": {
@@ -7349,15 +7258,15 @@
       }
     },
     "node_modules/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": "2.0.3",
+      "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz",
+      "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==",
       "dev": true,
       "dependencies": {
         "escape-string-regexp": "^2.0.0"
       },
       "engines": {
-        "node": ">=8"
+        "node": ">=10"
       }
     },
     "node_modules/state-toggle": {
@@ -7515,13 +7424,18 @@
       "dev": true
     },
     "node_modules/table": {
-      "version": "6.0.7",
-      "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz",
-      "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==",
+      "version": "6.0.9",
+      "resolved": "https://registry.npmjs.org/table/-/table-6.0.9.tgz",
+      "integrity": "sha512-F3cLs9a3hL1Z7N4+EkSscsel3z55XT950AvB05bwayrNg5T1/gykXtigioTAjbltvbMSJvvhFCbnf6mX+ntnJQ==",
       "dev": true,
       "dependencies": {
-        "ajv": "^7.0.2",
-        "lodash": "^4.17.20",
+        "ajv": "^8.0.1",
+        "is-boolean-object": "^1.1.0",
+        "is-number-object": "^1.0.4",
+        "is-string": "^1.0.5",
+        "lodash.clonedeep": "^4.5.0",
+        "lodash.flatten": "^4.4.0",
+        "lodash.truncate": "^4.4.2",
         "slice-ansi": "^4.0.0",
         "string-width": "^4.2.0"
       },
@@ -7530,9 +7444,9 @@
       }
     },
     "node_modules/table/node_modules/ajv": {
-      "version": "7.2.3",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.2.3.tgz",
-      "integrity": "sha512-idv5WZvKVXDqKralOImQgPM9v6WOdLNa0IY3B3doOjw/YxRGT8I+allIJ6kd7Uaj+SF1xZUSU+nPM5aDNBVtnw==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz",
+      "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==",
       "dev": true,
       "dependencies": {
         "fast-deep-equal": "^3.1.1",
@@ -7596,25 +7510,19 @@
       }
     },
     "node_modules/tap": {
-      "version": "14.11.0",
-      "resolved": "https://registry.npmjs.org/tap/-/tap-14.11.0.tgz",
-      "integrity": "sha512-z8qnNFVyIjLh/bNoTLFRkEk09XZUDAZbCkz/BjvHHly3ao5H+y60gPnedALfheEjA6dA4tpp/mrKq2NWlMuq0A==",
+      "version": "15.0.2",
+      "resolved": "https://registry.npmjs.org/tap/-/tap-15.0.2.tgz",
+      "integrity": "sha512-HfEahBCFIA/t3YuBZxkgfu9UiLqpOo/ibCs1xgGwJSWNqdmIxF8tiPwmgni+7SlNtmf0jNfYjT2xeatfZ7t/QA==",
       "bundleDependencies": [
         "ink",
         "treport",
         "@types/react",
-        "import-jsx",
-        "minipass",
-        "signal-exit",
-        "tap-parser",
-        "tap-yaml",
-        "yaml",
         "@babel/code-frame",
+        "@babel/compat-data",
         "@babel/core",
         "@babel/generator",
         "@babel/helper-annotate-as-pure",
-        "@babel/helper-builder-react-jsx",
-        "@babel/helper-builder-react-jsx-experimental",
+        "@babel/helper-compilation-targets",
         "@babel/helper-function-name",
         "@babel/helper-get-function-arity",
         "@babel/helper-member-expression-to-functions",
@@ -7626,6 +7534,7 @@
         "@babel/helper-simple-access",
         "@babel/helper-split-export-declaration",
         "@babel/helper-validator-identifier",
+        "@babel/helper-validator-option",
         "@babel/helpers",
         "@babel/highlight",
         "@babel/parser",
@@ -7638,19 +7547,22 @@
         "@babel/template",
         "@babel/traverse",
         "@babel/types",
-        "@types/color-name",
         "@types/prop-types",
+        "@types/scheduler",
         "@types/yoga-layout",
         "ansi-escapes",
-        "ansi-regex",
         "ansi-styles",
         "ansicolors",
         "arrify",
         "astral-regex",
         "auto-bind",
+        "balanced-match",
+        "brace-expansion",
+        "browserslist",
         "caller-callsite",
         "caller-path",
         "callsites",
+        "caniuse-lite",
         "cardinal",
         "chalk",
         "ci-info",
@@ -7658,107 +7570,137 @@
         "cli-truncate",
         "color-convert",
         "color-name",
+        "colorette",
+        "commondir",
+        "concat-map",
         "convert-source-map",
         "csstype",
         "debug",
+        "electron-to-chromium",
         "emoji-regex",
+        "escalade",
         "escape-string-regexp",
         "esprima",
         "events-to-array",
+        "find-cache-dir",
+        "find-up",
+        "fs.realpath",
         "gensync",
+        "glob",
         "globals",
         "has-flag",
+        "import-jsx",
+        "inflight",
+        "inherits",
         "is-ci",
         "is-fullwidth-code-point",
         "js-tokens",
         "jsesc",
         "json5",
+        "locate-path",
         "lodash",
         "lodash.throttle",
         "log-update",
         "loose-envify",
+        "make-dir",
         "mimic-fn",
+        "minimatch",
         "minimist",
+        "minipass",
         "ms",
+        "node-releases",
         "object-assign",
+        "once",
         "onetime",
-        "path-parse",
+        "p-limit",
+        "p-locate",
+        "p-try",
+        "path-exists",
+        "path-is-absolute",
+        "pkg-dir",
         "prop-types",
         "punycode",
         "react-is",
         "react-reconciler",
         "redeyed",
-        "resolve",
         "resolve-from",
         "restore-cursor",
+        "rimraf",
+        "safe-buffer",
         "scheduler",
         "semver",
+        "signal-exit",
         "slice-ansi",
+        "source-map",
         "string-length",
         "string-width",
-        "strip-ansi",
         "supports-color",
+        "tap-parser",
+        "tap-yaml",
         "to-fast-properties",
         "type-fest",
         "unicode-length",
         "widest-line",
         "wrap-ansi",
+        "wrappy",
+        "yallist",
+        "yaml",
         "yoga-layout-prebuilt"
       ],
       "dev": true,
       "dependencies": {
-        "@types/react": "^16.9.16",
-        "async-hook-domain": "^1.1.3",
-        "bind-obj-methods": "^2.0.0",
-        "browser-process-hrtime": "^1.0.0",
+        "@types/react": "^16.9.23",
         "chokidar": "^3.3.0",
-        "color-support": "^1.1.0",
         "coveralls": "^3.0.11",
-        "diff": "^4.0.1",
-        "esm": "^3.2.25",
         "findit": "^2.0.0",
-        "flow-remove-types": "^2.112.0",
-        "foreground-child": "^1.3.3",
+        "foreground-child": "^2.0.0",
         "fs-exists-cached": "^1.0.0",
-        "function-loop": "^1.0.2",
         "glob": "^7.1.6",
-        "import-jsx": "^3.1.0",
-        "ink": "^2.6.0",
+        "import-jsx": "^4.0.0",
+        "ink": "^2.7.1",
         "isexe": "^2.0.0",
-        "istanbul-lib-processinfo": "^1.0.0",
+        "istanbul-lib-processinfo": "^2.0.2",
         "jackspeak": "^1.4.0",
+        "libtap": "^1.1.1",
         "minipass": "^3.1.1",
-        "mkdirp": "^0.5.4",
-        "nyc": "^14.1.1",
+        "mkdirp": "^1.0.4",
+        "nyc": "^15.1.0",
         "opener": "^1.5.1",
-        "own-or": "^1.0.0",
-        "own-or-env": "^1.0.1",
         "react": "^16.12.0",
-        "rimraf": "^2.7.1",
+        "rimraf": "^3.0.0",
         "signal-exit": "^3.0.0",
         "source-map-support": "^0.5.16",
-        "stack-utils": "^1.0.3",
         "tap-mocha-reporter": "^5.0.0",
         "tap-parser": "^10.0.1",
         "tap-yaml": "^1.0.0",
-        "tcompare": "^3.0.0",
-        "treport": "^1.0.2",
-        "trivial-deferred": "^1.0.1",
-        "ts-node": "^8.5.2",
-        "typescript": "^3.7.2",
-        "which": "^2.0.2",
-        "write-file-atomic": "^3.0.1",
-        "yaml": "^1.7.2",
-        "yapool": "^1.0.0"
+        "tcompare": "^5.0.4",
+        "treport": "^2.0.0",
+        "which": "^2.0.2"
       },
       "bin": {
         "tap": "bin/run.js"
       },
       "engines": {
-        "node": ">=8"
+        "node": ">=10"
       },
       "funding": {
         "url": "https://github.com/sponsors/isaacs"
+      },
+      "peerDependencies": {
+        "flow-remove-types": ">=2.112.0",
+        "ts-node": ">=8.5.2",
+        "typescript": ">=3.7.2"
+      },
+      "peerDependenciesMeta": {
+        "flow-remove-types": {
+          "optional": true
+        },
+        "ts-node": {
+          "optional": true
+        },
+        "typescript": {
+          "optional": true
+        }
       }
     },
     "node_modules/tap-mocha-reporter": {
@@ -7819,35 +7761,40 @@
       }
     },
     "node_modules/tap/node_modules/@babel/code-frame": {
-      "version": "7.10.4",
+      "version": "7.12.13",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/highlight": "^7.10.4"
+        "@babel/highlight": "^7.12.13"
       }
     },
+    "node_modules/tap/node_modules/@babel/compat-data": {
+      "version": "7.13.12",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
     "node_modules/tap/node_modules/@babel/core": {
-      "version": "7.10.5",
+      "version": "7.13.14",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/code-frame": "^7.10.4",
-        "@babel/generator": "^7.10.5",
-        "@babel/helper-module-transforms": "^7.10.5",
-        "@babel/helpers": "^7.10.4",
-        "@babel/parser": "^7.10.5",
-        "@babel/template": "^7.10.4",
-        "@babel/traverse": "^7.10.5",
-        "@babel/types": "^7.10.5",
+        "@babel/code-frame": "^7.12.13",
+        "@babel/generator": "^7.13.9",
+        "@babel/helper-compilation-targets": "^7.13.13",
+        "@babel/helper-module-transforms": "^7.13.14",
+        "@babel/helpers": "^7.13.10",
+        "@babel/parser": "^7.13.13",
+        "@babel/template": "^7.12.13",
+        "@babel/traverse": "^7.13.13",
+        "@babel/types": "^7.13.14",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
-        "gensync": "^1.0.0-beta.1",
+        "gensync": "^1.0.0-beta.2",
         "json5": "^2.1.2",
-        "lodash": "^4.17.19",
-        "resolve": "^1.3.2",
-        "semver": "^5.4.1",
+        "semver": "^6.3.0",
         "source-map": "^0.5.0"
       },
       "engines": {
@@ -7858,194 +7805,176 @@
         "url": "https://opencollective.com/babel"
       }
     },
-    "node_modules/tap/node_modules/@babel/core/node_modules/source-map": {
-      "version": "0.5.7",
-      "dev": true,
-      "inBundle": true,
-      "license": "BSD-3-Clause",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/tap/node_modules/@babel/generator": {
-      "version": "7.10.5",
+      "version": "7.13.9",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/types": "^7.10.5",
+        "@babel/types": "^7.13.0",
         "jsesc": "^2.5.1",
         "source-map": "^0.5.0"
       }
     },
-    "node_modules/tap/node_modules/@babel/generator/node_modules/source-map": {
-      "version": "0.5.7",
-      "dev": true,
-      "inBundle": true,
-      "license": "BSD-3-Clause",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/tap/node_modules/@babel/helper-annotate-as-pure": {
-      "version": "7.10.4",
-      "dev": true,
-      "inBundle": true,
-      "license": "MIT",
-      "dependencies": {
-        "@babel/types": "^7.10.4"
-      }
-    },
-    "node_modules/tap/node_modules/@babel/helper-builder-react-jsx": {
-      "version": "7.10.4",
+      "version": "7.12.13",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.10.4",
-        "@babel/types": "^7.10.4"
+        "@babel/types": "^7.12.13"
       }
     },
-    "node_modules/tap/node_modules/@babel/helper-builder-react-jsx-experimental": {
-      "version": "7.10.5",
+    "node_modules/tap/node_modules/@babel/helper-compilation-targets": {
+      "version": "7.13.13",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.10.4",
-        "@babel/helper-module-imports": "^7.10.4",
-        "@babel/types": "^7.10.5"
+        "@babel/compat-data": "^7.13.12",
+        "@babel/helper-validator-option": "^7.12.17",
+        "browserslist": "^4.14.5",
+        "semver": "^6.3.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
       }
     },
     "node_modules/tap/node_modules/@babel/helper-function-name": {
-      "version": "7.10.4",
+      "version": "7.12.13",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-get-function-arity": "^7.10.4",
-        "@babel/template": "^7.10.4",
-        "@babel/types": "^7.10.4"
+        "@babel/helper-get-function-arity": "^7.12.13",
+        "@babel/template": "^7.12.13",
+        "@babel/types": "^7.12.13"
       }
     },
     "node_modules/tap/node_modules/@babel/helper-get-function-arity": {
-      "version": "7.10.4",
+      "version": "7.12.13",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/types": "^7.10.4"
+        "@babel/types": "^7.12.13"
       }
     },
     "node_modules/tap/node_modules/@babel/helper-member-expression-to-functions": {
-      "version": "7.10.5",
+      "version": "7.13.12",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/types": "^7.10.5"
+        "@babel/types": "^7.13.12"
       }
     },
     "node_modules/tap/node_modules/@babel/helper-module-imports": {
-      "version": "7.10.4",
+      "version": "7.13.12",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/types": "^7.10.4"
+        "@babel/types": "^7.13.12"
       }
     },
     "node_modules/tap/node_modules/@babel/helper-module-transforms": {
-      "version": "7.10.5",
+      "version": "7.13.14",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-module-imports": "^7.10.4",
-        "@babel/helper-replace-supers": "^7.10.4",
-        "@babel/helper-simple-access": "^7.10.4",
-        "@babel/helper-split-export-declaration": "^7.10.4",
-        "@babel/template": "^7.10.4",
-        "@babel/types": "^7.10.5",
-        "lodash": "^4.17.19"
+        "@babel/helper-module-imports": "^7.13.12",
+        "@babel/helper-replace-supers": "^7.13.12",
+        "@babel/helper-simple-access": "^7.13.12",
+        "@babel/helper-split-export-declaration": "^7.12.13",
+        "@babel/helper-validator-identifier": "^7.12.11",
+        "@babel/template": "^7.12.13",
+        "@babel/traverse": "^7.13.13",
+        "@babel/types": "^7.13.14"
       }
     },
     "node_modules/tap/node_modules/@babel/helper-optimise-call-expression": {
-      "version": "7.10.4",
+      "version": "7.12.13",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/types": "^7.10.4"
+        "@babel/types": "^7.12.13"
       }
     },
     "node_modules/tap/node_modules/@babel/helper-plugin-utils": {
-      "version": "7.10.4",
+      "version": "7.13.0",
       "dev": true,
       "inBundle": true,
       "license": "MIT"
     },
     "node_modules/tap/node_modules/@babel/helper-replace-supers": {
-      "version": "7.10.4",
+      "version": "7.13.12",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-member-expression-to-functions": "^7.10.4",
-        "@babel/helper-optimise-call-expression": "^7.10.4",
-        "@babel/traverse": "^7.10.4",
-        "@babel/types": "^7.10.4"
+        "@babel/helper-member-expression-to-functions": "^7.13.12",
+        "@babel/helper-optimise-call-expression": "^7.12.13",
+        "@babel/traverse": "^7.13.0",
+        "@babel/types": "^7.13.12"
       }
     },
     "node_modules/tap/node_modules/@babel/helper-simple-access": {
-      "version": "7.10.4",
+      "version": "7.13.12",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/template": "^7.10.4",
-        "@babel/types": "^7.10.4"
+        "@babel/types": "^7.13.12"
       }
     },
     "node_modules/tap/node_modules/@babel/helper-split-export-declaration": {
-      "version": "7.10.4",
+      "version": "7.12.13",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/types": "^7.10.4"
+        "@babel/types": "^7.12.13"
       }
     },
     "node_modules/tap/node_modules/@babel/helper-validator-identifier": {
-      "version": "7.10.4",
+      "version": "7.12.11",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/@babel/helper-validator-option": {
+      "version": "7.12.17",
       "dev": true,
       "inBundle": true,
       "license": "MIT"
     },
     "node_modules/tap/node_modules/@babel/helpers": {
-      "version": "7.10.4",
+      "version": "7.13.10",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/template": "^7.10.4",
-        "@babel/traverse": "^7.10.4",
-        "@babel/types": "^7.10.4"
+        "@babel/template": "^7.12.13",
+        "@babel/traverse": "^7.13.0",
+        "@babel/types": "^7.13.0"
       }
     },
     "node_modules/tap/node_modules/@babel/highlight": {
-      "version": "7.10.4",
+      "version": "7.13.10",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-validator-identifier": "^7.10.4",
+        "@babel/helper-validator-identifier": "^7.12.11",
         "chalk": "^2.0.0",
         "js-tokens": "^4.0.0"
       }
     },
     "node_modules/tap/node_modules/@babel/parser": {
-      "version": "7.10.5",
+      "version": "7.13.13",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
@@ -8057,26 +7986,28 @@
       }
     },
     "node_modules/tap/node_modules/@babel/plugin-proposal-object-rest-spread": {
-      "version": "7.10.4",
+      "version": "7.13.8",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.10.4",
-        "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
-        "@babel/plugin-transform-parameters": "^7.10.4"
+        "@babel/compat-data": "^7.13.8",
+        "@babel/helper-compilation-targets": "^7.13.8",
+        "@babel/helper-plugin-utils": "^7.13.0",
+        "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+        "@babel/plugin-transform-parameters": "^7.13.0"
       },
       "peerDependencies": {
         "@babel/core": "^7.0.0-0"
       }
     },
     "node_modules/tap/node_modules/@babel/plugin-syntax-jsx": {
-      "version": "7.10.4",
+      "version": "7.12.13",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.10.4"
+        "@babel/helper-plugin-utils": "^7.12.13"
       },
       "peerDependencies": {
         "@babel/core": "^7.0.0-0"
@@ -8095,90 +8026,83 @@
       }
     },
     "node_modules/tap/node_modules/@babel/plugin-transform-destructuring": {
-      "version": "7.10.4",
+      "version": "7.13.0",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.10.4"
+        "@babel/helper-plugin-utils": "^7.13.0"
       },
       "peerDependencies": {
         "@babel/core": "^7.0.0-0"
       }
     },
     "node_modules/tap/node_modules/@babel/plugin-transform-parameters": {
-      "version": "7.10.5",
+      "version": "7.13.0",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-get-function-arity": "^7.10.4",
-        "@babel/helper-plugin-utils": "^7.10.4"
+        "@babel/helper-plugin-utils": "^7.13.0"
       },
       "peerDependencies": {
         "@babel/core": "^7.0.0-0"
       }
     },
     "node_modules/tap/node_modules/@babel/plugin-transform-react-jsx": {
-      "version": "7.10.4",
+      "version": "7.13.12",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-builder-react-jsx": "^7.10.4",
-        "@babel/helper-builder-react-jsx-experimental": "^7.10.4",
-        "@babel/helper-plugin-utils": "^7.10.4",
-        "@babel/plugin-syntax-jsx": "^7.10.4"
+        "@babel/helper-annotate-as-pure": "^7.12.13",
+        "@babel/helper-module-imports": "^7.13.12",
+        "@babel/helper-plugin-utils": "^7.13.0",
+        "@babel/plugin-syntax-jsx": "^7.12.13",
+        "@babel/types": "^7.13.12"
       },
       "peerDependencies": {
         "@babel/core": "^7.0.0-0"
       }
     },
     "node_modules/tap/node_modules/@babel/template": {
-      "version": "7.10.4",
+      "version": "7.12.13",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/code-frame": "^7.10.4",
-        "@babel/parser": "^7.10.4",
-        "@babel/types": "^7.10.4"
+        "@babel/code-frame": "^7.12.13",
+        "@babel/parser": "^7.12.13",
+        "@babel/types": "^7.12.13"
       }
     },
     "node_modules/tap/node_modules/@babel/traverse": {
-      "version": "7.10.5",
+      "version": "7.13.13",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/code-frame": "^7.10.4",
-        "@babel/generator": "^7.10.5",
-        "@babel/helper-function-name": "^7.10.4",
-        "@babel/helper-split-export-declaration": "^7.10.4",
-        "@babel/parser": "^7.10.5",
-        "@babel/types": "^7.10.5",
+        "@babel/code-frame": "^7.12.13",
+        "@babel/generator": "^7.13.9",
+        "@babel/helper-function-name": "^7.12.13",
+        "@babel/helper-split-export-declaration": "^7.12.13",
+        "@babel/parser": "^7.13.13",
+        "@babel/types": "^7.13.13",
         "debug": "^4.1.0",
-        "globals": "^11.1.0",
-        "lodash": "^4.17.19"
+        "globals": "^11.1.0"
       }
     },
     "node_modules/tap/node_modules/@babel/types": {
-      "version": "7.10.5",
+      "version": "7.13.14",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-validator-identifier": "^7.10.4",
+        "@babel/helper-validator-identifier": "^7.12.11",
         "lodash": "^4.17.19",
         "to-fast-properties": "^2.0.0"
       }
     },
-    "node_modules/tap/node_modules/@types/color-name": {
-      "version": "1.1.1",
-      "dev": true,
-      "inBundle": true,
-      "license": "MIT"
-    },
     "node_modules/tap/node_modules/@types/prop-types": {
       "version": "15.7.3",
       "dev": true,
@@ -8186,15 +8110,22 @@
       "license": "MIT"
     },
     "node_modules/tap/node_modules/@types/react": {
-      "version": "16.9.43",
+      "version": "16.14.5",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
         "@types/prop-types": "*",
-        "csstype": "^2.2.0"
+        "@types/scheduler": "*",
+        "csstype": "^3.0.2"
       }
     },
+    "node_modules/tap/node_modules/@types/scheduler": {
+      "version": "0.16.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
     "node_modules/tap/node_modules/@types/yoga-layout": {
       "version": "1.9.2",
       "dev": true,
@@ -8202,12 +8133,12 @@
       "license": "MIT"
     },
     "node_modules/tap/node_modules/ansi-escapes": {
-      "version": "4.3.1",
+      "version": "4.3.2",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "type-fest": "^0.11.0"
+        "type-fest": "^0.21.3"
       },
       "engines": {
         "node": ">=8"
@@ -8216,15 +8147,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/tap/node_modules/ansi-regex": {
-      "version": "5.0.0",
-      "dev": true,
-      "inBundle": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/tap/node_modules/ansi-styles": {
       "version": "3.2.1",
       "dev": true,
@@ -8273,8 +8195,47 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/tap/node_modules/caller-callsite": {
-      "version": "2.0.0",
+    "node_modules/tap/node_modules/balanced-match": {
+      "version": "1.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/tap/node_modules/browserslist": {
+      "version": "4.16.3",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "caniuse-lite": "^1.0.30001181",
+        "colorette": "^1.2.1",
+        "electron-to-chromium": "^1.3.649",
+        "escalade": "^3.1.1",
+        "node-releases": "^1.1.70"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/browserslist"
+      }
+    },
+    "node_modules/tap/node_modules/caller-callsite": {
+      "version": "2.0.0",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
@@ -8306,6 +8267,12 @@
         "node": ">=4"
       }
     },
+    "node_modules/tap/node_modules/caniuse-lite": {
+      "version": "1.0.30001204",
+      "dev": true,
+      "inBundle": true,
+      "license": "CC-BY-4.0"
+    },
     "node_modules/tap/node_modules/cardinal": {
       "version": "2.1.1",
       "dev": true,
@@ -8382,6 +8349,24 @@
       "inBundle": true,
       "license": "MIT"
     },
+    "node_modules/tap/node_modules/colorette": {
+      "version": "1.2.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/commondir": {
+      "version": "1.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/concat-map": {
+      "version": "0.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
     "node_modules/tap/node_modules/convert-source-map": {
       "version": "1.7.0",
       "dev": true,
@@ -8391,35 +8376,34 @@
         "safe-buffer": "~5.1.1"
       }
     },
-    "node_modules/tap/node_modules/convert-source-map/node_modules/safe-buffer": {
-      "version": "5.1.2",
-      "dev": true,
-      "inBundle": true,
-      "license": "MIT"
-    },
     "node_modules/tap/node_modules/csstype": {
-      "version": "2.6.11",
+      "version": "3.0.7",
       "dev": true,
       "inBundle": true,
       "license": "MIT"
     },
     "node_modules/tap/node_modules/debug": {
-      "version": "4.1.1",
+      "version": "4.3.1",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "ms": "^2.1.1"
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
       }
     },
-    "node_modules/tap/node_modules/diff": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
-      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+    "node_modules/tap/node_modules/electron-to-chromium": {
+      "version": "1.3.703",
       "dev": true,
-      "engines": {
-        "node": ">=0.3.1"
-      }
+      "inBundle": true,
+      "license": "ISC"
     },
     "node_modules/tap/node_modules/emoji-regex": {
       "version": "8.0.0",
@@ -8427,6 +8411,15 @@
       "inBundle": true,
       "license": "MIT"
     },
+    "node_modules/tap/node_modules/escalade": {
+      "version": "3.1.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/tap/node_modules/escape-string-regexp": {
       "version": "1.0.5",
       "dev": true,
@@ -8455,8 +8448,44 @@
       "inBundle": true,
       "license": "ISC"
     },
+    "node_modules/tap/node_modules/find-cache-dir": {
+      "version": "3.3.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "commondir": "^1.0.1",
+        "make-dir": "^3.0.2",
+        "pkg-dir": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/avajs/find-cache-dir?sponsor=1"
+      }
+    },
+    "node_modules/tap/node_modules/find-up": {
+      "version": "4.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC"
+    },
     "node_modules/tap/node_modules/gensync": {
-      "version": "1.0.0-beta.1",
+      "version": "1.0.0-beta.2",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
@@ -8464,6 +8493,26 @@
         "node": ">=6.9.0"
       }
     },
+    "node_modules/tap/node_modules/glob": {
+      "version": "7.1.6",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "dependencies": {
+        "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"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
     "node_modules/tap/node_modules/globals": {
       "version": "11.12.0",
       "dev": true,
@@ -8483,7 +8532,7 @@
       }
     },
     "node_modules/tap/node_modules/import-jsx": {
-      "version": "3.1.0",
+      "version": "4.0.0",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
@@ -8493,12 +8542,31 @@
         "@babel/plugin-transform-destructuring": "^7.5.0",
         "@babel/plugin-transform-react-jsx": "^7.3.0",
         "caller-path": "^2.0.0",
-        "resolve-from": "^3.0.0"
+        "find-cache-dir": "^3.2.0",
+        "make-dir": "^3.0.2",
+        "resolve-from": "^3.0.0",
+        "rimraf": "^3.0.0"
       },
       "engines": {
-        "node": ">= 4"
+        "node": ">=10"
       }
     },
+    "node_modules/tap/node_modules/inflight": {
+      "version": "1.0.6",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/tap/node_modules/inherits": {
+      "version": "2.0.4",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC"
+    },
     "node_modules/tap/node_modules/ink": {
       "version": "2.7.1",
       "dev": true,
@@ -8538,12 +8606,11 @@
       }
     },
     "node_modules/tap/node_modules/ink/node_modules/ansi-styles": {
-      "version": "4.2.1",
+      "version": "4.3.0",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@types/color-name": "^1.1.1",
         "color-convert": "^2.0.1"
       },
       "engines": {
@@ -8594,7 +8661,7 @@
       }
     },
     "node_modules/tap/node_modules/ink/node_modules/supports-color": {
-      "version": "7.1.0",
+      "version": "7.2.0",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
@@ -8645,7 +8712,7 @@
       }
     },
     "node_modules/tap/node_modules/json5": {
-      "version": "2.1.3",
+      "version": "2.2.0",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
@@ -8659,8 +8726,20 @@
         "node": ">=6"
       }
     },
+    "node_modules/tap/node_modules/locate-path": {
+      "version": "5.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "p-locate": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/tap/node_modules/lodash": {
-      "version": "4.17.19",
+      "version": "4.17.21",
       "dev": true,
       "inBundle": true,
       "license": "MIT"
@@ -8819,6 +8898,21 @@
         "loose-envify": "cli.js"
       }
     },
+    "node_modules/tap/node_modules/make-dir": {
+      "version": "3.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "semver": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/tap/node_modules/mimic-fn": {
       "version": "2.1.0",
       "dev": true,
@@ -8828,6 +8922,18 @@
         "node": ">=6"
       }
     },
+    "node_modules/tap/node_modules/minimatch": {
+      "version": "3.0.4",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/tap/node_modules/minimist": {
       "version": "1.2.5",
       "dev": true,
@@ -8846,26 +8952,14 @@
         "node": ">=8"
       }
     },
-    "node_modules/tap/node_modules/minipass/node_modules/yallist": {
-      "version": "4.0.0",
+    "node_modules/tap/node_modules/ms": {
+      "version": "2.1.2",
       "dev": true,
       "inBundle": true,
-      "license": "ISC"
-    },
-    "node_modules/tap/node_modules/mkdirp": {
-      "version": "0.5.5",
-      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
-      "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
-      "dev": true,
-      "dependencies": {
-        "minimist": "^1.2.5"
-      },
-      "bin": {
-        "mkdirp": "bin/cmd.js"
-      }
+      "license": "MIT"
     },
-    "node_modules/tap/node_modules/ms": {
-      "version": "2.1.2",
+    "node_modules/tap/node_modules/node-releases": {
+      "version": "1.1.71",
       "dev": true,
       "inBundle": true,
       "license": "MIT"
@@ -8879,8 +8973,17 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/tap/node_modules/once": {
+      "version": "1.4.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
     "node_modules/tap/node_modules/onetime": {
-      "version": "5.1.0",
+      "version": "5.1.2",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
@@ -8889,13 +8992,76 @@
       },
       "engines": {
         "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/tap/node_modules/path-parse": {
-      "version": "1.0.6",
+    "node_modules/tap/node_modules/p-limit": {
+      "version": "2.3.0",
       "dev": true,
       "inBundle": true,
-      "license": "MIT"
+      "license": "MIT",
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/tap/node_modules/p-locate": {
+      "version": "4.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/p-try": {
+      "version": "2.2.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tap/node_modules/path-exists": {
+      "version": "4.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/tap/node_modules/pkg-dir": {
+      "version": "4.2.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "find-up": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
     },
     "node_modules/tap/node_modules/prop-types": {
       "version": "15.7.2",
@@ -8950,18 +9116,6 @@
         "esprima": "~4.0.0"
       }
     },
-    "node_modules/tap/node_modules/resolve": {
-      "version": "1.17.0",
-      "dev": true,
-      "inBundle": true,
-      "license": "MIT",
-      "dependencies": {
-        "path-parse": "^1.0.6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
     "node_modules/tap/node_modules/resolve-from": {
       "version": "3.0.0",
       "dev": true,
@@ -8985,17 +9139,26 @@
       }
     },
     "node_modules/tap/node_modules/rimraf": {
-      "version": "2.7.1",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-      "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+      "version": "3.0.2",
       "dev": true,
+      "inBundle": true,
+      "license": "ISC",
       "dependencies": {
         "glob": "^7.1.3"
       },
       "bin": {
         "rimraf": "bin.js"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
       }
     },
+    "node_modules/tap/node_modules/safe-buffer": {
+      "version": "5.1.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
     "node_modules/tap/node_modules/scheduler": {
       "version": "0.18.0",
       "dev": true,
@@ -9007,12 +9170,12 @@
       }
     },
     "node_modules/tap/node_modules/semver": {
-      "version": "5.7.1",
+      "version": "6.3.0",
       "dev": true,
       "inBundle": true,
       "license": "ISC",
       "bin": {
-        "semver": "bin/semver"
+        "semver": "bin/semver.js"
       }
     },
     "node_modules/tap/node_modules/signal-exit": {
@@ -9036,12 +9199,11 @@
       }
     },
     "node_modules/tap/node_modules/slice-ansi/node_modules/ansi-styles": {
-      "version": "4.2.1",
+      "version": "4.3.0",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@types/color-name": "^1.1.1",
         "color-convert": "^2.0.1"
       },
       "engines": {
@@ -9069,6 +9231,15 @@
       "inBundle": true,
       "license": "MIT"
     },
+    "node_modules/tap/node_modules/source-map": {
+      "version": "0.5.7",
+      "dev": true,
+      "inBundle": true,
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/tap/node_modules/string-length": {
       "version": "3.1.0",
       "dev": true,
@@ -9113,7 +9284,7 @@
       }
     },
     "node_modules/tap/node_modules/string-width": {
-      "version": "4.2.0",
+      "version": "4.2.2",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
@@ -9126,7 +9297,16 @@
         "node": ">=8"
       }
     },
-    "node_modules/tap/node_modules/strip-ansi": {
+    "node_modules/tap/node_modules/string-width/node_modules/ansi-regex": {
+      "version": "5.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/string-width/node_modules/strip-ansi": {
       "version": "6.0.0",
       "dev": true,
       "inBundle": true,
@@ -9151,7 +9331,7 @@
       }
     },
     "node_modules/tap/node_modules/tap-parser": {
-      "version": "10.0.1",
+      "version": "10.1.0",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
@@ -9186,14 +9366,14 @@
       }
     },
     "node_modules/tap/node_modules/treport": {
-      "version": "1.0.2",
+      "version": "2.0.0",
       "dev": true,
       "inBundle": true,
       "license": "ISC",
       "dependencies": {
         "cardinal": "^2.1.1",
         "chalk": "^3.0.0",
-        "import-jsx": "^3.1.0",
+        "import-jsx": "^4.0.0",
         "ink": "^2.6.0",
         "ms": "^2.1.2",
         "string-length": "^3.1.0",
@@ -9205,12 +9385,11 @@
       }
     },
     "node_modules/tap/node_modules/treport/node_modules/ansi-styles": {
-      "version": "4.2.1",
+      "version": "4.3.0",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@types/color-name": "^1.1.1",
         "color-convert": "^2.0.1"
       },
       "engines": {
@@ -9261,7 +9440,7 @@
       }
     },
     "node_modules/tap/node_modules/treport/node_modules/supports-color": {
-      "version": "7.1.0",
+      "version": "7.2.0",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
@@ -9273,12 +9452,12 @@
       }
     },
     "node_modules/tap/node_modules/type-fest": {
-      "version": "0.11.0",
+      "version": "0.21.3",
       "dev": true,
       "inBundle": true,
       "license": "(MIT OR CC0-1.0)",
       "engines": {
-        "node": ">=8"
+        "node": ">=10"
       },
       "funding": {
         "url": "https://github.com/sponsors/sindresorhus"
@@ -9341,13 +9520,21 @@
         "node": ">=8"
       }
     },
+    "node_modules/tap/node_modules/wrap-ansi/node_modules/ansi-regex": {
+      "version": "5.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/tap/node_modules/wrap-ansi/node_modules/ansi-styles": {
-      "version": "4.2.1",
+      "version": "4.3.0",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
       "dependencies": {
-        "@types/color-name": "^1.1.1",
         "color-convert": "^2.0.1"
       },
       "engines": {
@@ -9375,8 +9562,32 @@
       "inBundle": true,
       "license": "MIT"
     },
+    "node_modules/tap/node_modules/wrap-ansi/node_modules/strip-ansi": {
+      "version": "6.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "ansi-regex": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/wrappy": {
+      "version": "1.0.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC"
+    },
+    "node_modules/tap/node_modules/yallist": {
+      "version": "4.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC"
+    },
     "node_modules/tap/node_modules/yaml": {
-      "version": "1.10.0",
+      "version": "1.10.2",
       "dev": true,
       "inBundle": true,
       "license": "ISC",
@@ -9385,7 +9596,7 @@
       }
     },
     "node_modules/tap/node_modules/yoga-layout-prebuilt": {
-      "version": "1.9.6",
+      "version": "1.10.0",
       "dev": true,
       "inBundle": true,
       "license": "MIT",
@@ -9458,195 +9669,42 @@
         "util-deprecate": "^1.0.1"
       },
       "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/tcompare": {
-      "version": "3.0.5",
-      "resolved": "https://registry.npmjs.org/tcompare/-/tcompare-3.0.5.tgz",
-      "integrity": "sha512-+tmloQj1buaShBX+LP1i1NF5riJm110Yr0flIJAEoKf01tFVoMZvW2jq1JLqaW8fspOUVPm5NKKW5qLwT0ETDQ==",
-      "dev": true,
-      "dependencies": {
-        "diff-frag": "^1.0.1"
-      }
-    },
-    "node_modules/test-exclude": {
-      "version": "5.2.3",
-      "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz",
-      "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==",
-      "dev": true,
-      "dependencies": {
-        "glob": "^7.1.3",
-        "minimatch": "^3.0.4",
-        "read-pkg-up": "^4.0.0",
-        "require-main-filename": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/test-exclude/node_modules/find-up": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
-      "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
-      "dev": true,
-      "dependencies": {
-        "locate-path": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/test-exclude/node_modules/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==",
-      "dev": true
-    },
-    "node_modules/test-exclude/node_modules/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,
-      "dependencies": {
-        "graceful-fs": "^4.1.2",
-        "parse-json": "^4.0.0",
-        "pify": "^3.0.0",
-        "strip-bom": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/test-exclude/node_modules/locate-path": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
-      "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
-      "dev": true,
-      "dependencies": {
-        "p-locate": "^3.0.0",
-        "path-exists": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/test-exclude/node_modules/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,
-      "dependencies": {
-        "hosted-git-info": "^2.1.4",
-        "resolve": "^1.10.0",
-        "semver": "2 || 3 || 4 || 5",
-        "validate-npm-package-license": "^3.0.1"
-      }
-    },
-    "node_modules/test-exclude/node_modules/p-limit": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
-      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
-      "dev": true,
-      "dependencies": {
-        "p-try": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/test-exclude/node_modules/p-locate": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
-      "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
-      "dev": true,
-      "dependencies": {
-        "p-limit": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/test-exclude/node_modules/p-try": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
-      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/test-exclude/node_modules/parse-json": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
-      "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
-      "dev": true,
-      "dependencies": {
-        "error-ex": "^1.3.1",
-        "json-parse-better-errors": "^1.0.1"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/test-exclude/node_modules/path-type": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
-      "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
-      "dev": true,
-      "dependencies": {
-        "pify": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/test-exclude/node_modules/pify": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-      "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
+        "node": ">= 6"
       }
     },
-    "node_modules/test-exclude/node_modules/read-pkg": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
-      "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
+    "node_modules/tcompare": {
+      "version": "5.0.4",
+      "resolved": "https://registry.npmjs.org/tcompare/-/tcompare-5.0.4.tgz",
+      "integrity": "sha512-worXBcrmLoFu9oJYAKznjPE89APTEXk/XCazuDuSQfK1EqX3bpLPW3cY/RQucbcc7mW+yKW0duujsuFlU7dRCA==",
       "dev": true,
       "dependencies": {
-        "load-json-file": "^4.0.0",
-        "normalize-package-data": "^2.3.2",
-        "path-type": "^3.0.0"
+        "diff": "^4.0.2"
       },
       "engines": {
-        "node": ">=4"
+        "node": ">=10"
       }
     },
-    "node_modules/test-exclude/node_modules/read-pkg-up": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz",
-      "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==",
+    "node_modules/tcompare/node_modules/diff": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
       "dev": true,
-      "dependencies": {
-        "find-up": "^3.0.0",
-        "read-pkg": "^3.0.0"
-      },
       "engines": {
-        "node": ">=6"
+        "node": ">=0.3.1"
       }
     },
-    "node_modules/test-exclude/node_modules/semver": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+    "node_modules/test-exclude": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+      "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
       "dev": true,
-      "bin": {
-        "semver": "bin/semver"
+      "dependencies": {
+        "@istanbuljs/schema": "^0.1.2",
+        "glob": "^7.1.4",
+        "minimatch": "^3.0.4"
+      },
+      "engines": {
+        "node": ">=8"
       }
     },
     "node_modules/text-table": {
@@ -9746,40 +9804,6 @@
         "url": "https://github.com/sponsors/wooorm"
       }
     },
-    "node_modules/ts-node": {
-      "version": "8.10.2",
-      "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz",
-      "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==",
-      "dev": true,
-      "dependencies": {
-        "arg": "^4.1.0",
-        "diff": "^4.0.1",
-        "make-error": "^1.1.1",
-        "source-map-support": "^0.5.17",
-        "yn": "3.1.1"
-      },
-      "bin": {
-        "ts-node": "dist/bin.js",
-        "ts-node-script": "dist/bin-script.js",
-        "ts-node-transpile-only": "dist/bin-transpile.js",
-        "ts-script": "dist/bin-script-deprecated.js"
-      },
-      "engines": {
-        "node": ">=6.0.0"
-      },
-      "peerDependencies": {
-        "typescript": ">=2.7"
-      }
-    },
-    "node_modules/ts-node/node_modules/diff": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
-      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.3.1"
-      }
-    },
     "node_modules/tsconfig-paths": {
       "version": "3.9.0",
       "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz",
@@ -9852,29 +9876,19 @@
         "is-typedarray": "^1.0.0"
       }
     },
-    "node_modules/typescript": {
-      "version": "3.9.9",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz",
-      "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==",
-      "dev": true,
-      "bin": {
-        "tsc": "bin/tsc",
-        "tsserver": "bin/tsserver"
-      },
-      "engines": {
-        "node": ">=4.2.0"
-      }
-    },
     "node_modules/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,
       "dependencies": {
         "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"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
       }
     },
     "node_modules/unherit": {
@@ -9978,9 +9992,9 @@
       }
     },
     "node_modules/unist-util-remove": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.0.1.tgz",
-      "integrity": "sha512-YtuetK6o16CMfG+0u4nndsWpujgsHDHHLyE0yGpJLLn5xSjKeyGyzEBOI2XbmoUHCYabmNgX52uxlWoQhcvR7Q==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz",
+      "integrity": "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==",
       "dev": true,
       "dependencies": {
         "unist-util-is": "^4.0.0"
@@ -10166,12 +10180,6 @@
         "url": "https://opencollective.com/unified"
       }
     },
-    "node_modules/vlq": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
-      "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==",
-      "dev": true
-    },
     "node_modules/w3c-hr-time": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
@@ -10305,12 +10313,6 @@
       "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
       "dev": true
     },
-    "node_modules/which-pm-runs": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
-      "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
-      "dev": true
-    },
     "node_modules/wide-align": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
@@ -10429,9 +10431,9 @@
       }
     },
     "node_modules/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
     },
     "node_modules/yallist": {
@@ -10456,109 +10458,92 @@
       "dev": true
     },
     "node_modules/yargs": {
-      "version": "13.3.2",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
-      "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+      "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,
       "dependencies": {
-        "cliui": "^5.0.0",
-        "find-up": "^3.0.0",
+        "cliui": "^6.0.0",
+        "decamelize": "^1.2.0",
+        "find-up": "^4.1.0",
         "get-caller-file": "^2.0.1",
         "require-directory": "^2.1.1",
         "require-main-filename": "^2.0.0",
         "set-blocking": "^2.0.0",
-        "string-width": "^3.0.0",
+        "string-width": "^4.2.0",
         "which-module": "^2.0.0",
         "y18n": "^4.0.0",
-        "yargs-parser": "^13.1.2"
+        "yargs-parser": "^18.1.2"
+      },
+      "engines": {
+        "node": ">=8"
       }
     },
     "node_modules/yargs-parser": {
-      "version": "13.1.2",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
-      "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+      "version": "18.1.3",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+      "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
       "dev": true,
       "dependencies": {
         "camelcase": "^5.0.0",
         "decamelize": "^1.2.0"
-      }
-    },
-    "node_modules/yargs/node_modules/ansi-regex": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-      "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
-      "dev": true,
+      },
       "engines": {
         "node": ">=6"
       }
     },
-    "node_modules/yargs/node_modules/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==",
+    "node_modules/yargs/node_modules/ansi-regex": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+      "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
       "dev": true,
-      "dependencies": {
-        "color-convert": "^1.9.0"
-      },
       "engines": {
-        "node": ">=4"
+        "node": ">=8"
       }
     },
     "node_modules/yargs/node_modules/cliui": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
-      "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+      "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
       "dev": true,
       "dependencies": {
-        "string-width": "^3.1.0",
-        "strip-ansi": "^5.2.0",
-        "wrap-ansi": "^5.1.0"
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^6.2.0"
       }
     },
-    "node_modules/yargs/node_modules/color-convert": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+    "node_modules/yargs/node_modules/find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
       "dev": true,
       "dependencies": {
-        "color-name": "1.1.3"
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
       }
     },
-    "node_modules/yargs/node_modules/color-name": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
-      "dev": true
-    },
-    "node_modules/yargs/node_modules/emoji-regex": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
-      "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
-      "dev": true
-    },
-    "node_modules/yargs/node_modules/find-up": {
+    "node_modules/yargs/node_modules/is-fullwidth-code-point": {
       "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
-      "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+      "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,
-      "dependencies": {
-        "locate-path": "^3.0.0"
-      },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/yargs/node_modules/locate-path": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
-      "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
       "dev": true,
       "dependencies": {
-        "p-locate": "^3.0.0",
-        "path-exists": "^3.0.0"
+        "p-locate": "^4.1.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/yargs/node_modules/p-limit": {
@@ -10577,15 +10562,15 @@
       }
     },
     "node_modules/yargs/node_modules/p-locate": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
-      "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
       "dev": true,
       "dependencies": {
-        "p-limit": "^2.0.0"
+        "p-limit": "^2.2.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/yargs/node_modules/p-try": {
@@ -10597,53 +10582,53 @@
         "node": ">=6"
       }
     },
+    "node_modules/yargs/node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/yargs/node_modules/string-width": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-      "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
+      "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
       "dev": true,
       "dependencies": {
-        "emoji-regex": "^7.0.1",
-        "is-fullwidth-code-point": "^2.0.0",
-        "strip-ansi": "^5.1.0"
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/yargs/node_modules/strip-ansi": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-      "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+      "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
       "dev": true,
       "dependencies": {
-        "ansi-regex": "^4.1.0"
+        "ansi-regex": "^5.0.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/yargs/node_modules/wrap-ansi": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
-      "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+      "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
       "dev": true,
       "dependencies": {
-        "ansi-styles": "^3.2.0",
-        "string-width": "^3.0.0",
-        "strip-ansi": "^5.0.0"
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
       },
       "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/yn": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
-      "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
+        "node": ">=8"
       }
     },
     "node_modules/zwitch": {
@@ -10749,9 +10734,9 @@
       }
     },
     "@babel/helper-module-transforms": {
-      "version": "7.13.12",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.12.tgz",
-      "integrity": "sha512-7zVQqMO3V+K4JOOj40kxiCrMf6xlQAkewBB0eu2b03OO/Q21ZutOzjpfD79A5gtE/2OWi1nv625MrDlGlkbknQ==",
+      "version": "7.13.14",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.14.tgz",
+      "integrity": "sha512-QuU/OJ0iAOSIatyVZmfqB0lbkVP0kDRiKj34xy+QNsnVZi/PA6BoSoreeqnxxa9EHFAIL0R9XOaAR/G9WlIy5g==",
       "dev": true,
       "requires": {
         "@babel/helper-module-imports": "^7.13.12",
@@ -10760,8 +10745,8 @@
         "@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.12"
+        "@babel/traverse": "^7.13.13",
+        "@babel/types": "^7.13.14"
       }
     },
     "@babel/helper-optimise-call-expression": {
@@ -10896,9 +10881,9 @@
       }
     },
     "@babel/parser": {
-      "version": "7.13.12",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.12.tgz",
-      "integrity": "sha512-4T7Pb244rxH24yR116LAuJ+adxXXnHhZaLJjegJVKSdoNCe4x1eDBaud5YIcQFcqzsaD5BHvJw5BQ0AZapdCRw==",
+      "version": "7.13.15",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.15.tgz",
+      "integrity": "sha512-b9COtcAlVEQljy/9fbcMHpG+UIW9ReF+gpaxDHTlZd0c6/UU9ng8zdySAW9sRTzpvcdCHn6bUcbuYUgGzLAWVQ==",
       "dev": true
     },
     "@babel/plugin-proposal-object-rest-spread": {
@@ -10951,26 +10936,25 @@
       }
     },
     "@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==",
+      "version": "7.13.15",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.15.tgz",
+      "integrity": "sha512-/mpZMNvj6bce59Qzl09fHEs8Bt8NnpEDQYleHUPZQ3wXUMvXi+HJPLars68oAbmp839fGoOkv2pSL2z9ajCIaQ==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.12.13",
-        "@babel/generator": "^7.13.0",
+        "@babel/generator": "^7.13.9",
         "@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",
+        "@babel/parser": "^7.13.15",
+        "@babel/types": "^7.13.14",
         "debug": "^4.1.0",
-        "globals": "^11.1.0",
-        "lodash": "^4.17.19"
+        "globals": "^11.1.0"
       }
     },
     "@babel/types": {
-      "version": "7.13.12",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.12.tgz",
-      "integrity": "sha512-K4nY2xFN4QMvQwkQ+zmBDp6ANMbVNw6BbxWmYA4qNjhR9W+Lj/8ky5MEY2Me5r+B2c6/v6F53oMndG+f9s3IiA==",
+      "version": "7.13.14",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz",
+      "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==",
       "dev": true,
       "requires": {
         "@babel/helper-validator-identifier": "^7.12.11",
@@ -11012,6 +10996,82 @@
         }
       }
     },
+    "@istanbuljs/load-nyc-config": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+      "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+      "dev": true,
+      "requires": {
+        "camelcase": "^5.3.1",
+        "find-up": "^4.1.0",
+        "get-package-type": "^0.1.0",
+        "js-yaml": "^3.13.1",
+        "resolve-from": "^5.0.0"
+      },
+      "dependencies": {
+        "find-up": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+          "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+          "dev": true,
+          "requires": {
+            "locate-path": "^5.0.0",
+            "path-exists": "^4.0.0"
+          }
+        },
+        "locate-path": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+          "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+          "dev": true,
+          "requires": {
+            "p-locate": "^4.1.0"
+          }
+        },
+        "p-limit": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+          "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+          "dev": true,
+          "requires": {
+            "p-try": "^2.0.0"
+          }
+        },
+        "p-locate": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+          "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+          "dev": true,
+          "requires": {
+            "p-limit": "^2.2.0"
+          }
+        },
+        "p-try": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+          "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+          "dev": true
+        },
+        "path-exists": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+          "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+          "dev": true
+        },
+        "resolve-from": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+          "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+          "dev": true
+        }
+      }
+    },
+    "@istanbuljs/schema": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+      "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+      "dev": true
+    },
     "@mdx-js/mdx": {
       "version": "1.6.22",
       "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz",
@@ -11337,9 +11397,9 @@
       "integrity": "sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk="
     },
     "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",
@@ -11347,12 +11407,12 @@
       }
     },
     "append-transform": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz",
-      "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz",
+      "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==",
       "dev": true,
       "requires": {
-        "default-require-extensions": "^2.0.0"
+        "default-require-extensions": "^3.0.0"
       }
     },
     "aproba": {
@@ -11374,12 +11434,6 @@
         "readable-stream": "^2.0.6"
       }
     },
-    "arg": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
-      "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
-      "dev": true
-    },
     "argparse": {
       "version": "1.0.10",
       "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@@ -11444,13 +11498,10 @@
       "dev": true
     },
     "async-hook-domain": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/async-hook-domain/-/async-hook-domain-1.1.3.tgz",
-      "integrity": "sha512-ZovMxSbADV3+biB7oR1GL5lGyptI24alp0LWHlmz1OFc5oL47pz3EiIF6nXOkDW7yLqih4NtsiYduzdDW0i+Wg==",
-      "dev": true,
-      "requires": {
-        "source-map-support": "^0.5.11"
-      }
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/async-hook-domain/-/async-hook-domain-2.0.3.tgz",
+      "integrity": "sha512-MadiLLDEZRZzZwcm0dgS+K99qXZ4H2saAUwUgwzFulbAkXrKi3AX5FvWS3FFTQtLMwrqcGqAJe6o12KrObejQA==",
+      "dev": true
     },
     "asynckit": {
       "version": "0.4.0",
@@ -11509,9 +11560,9 @@
       "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",
@@ -11546,9 +11597,9 @@
       "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
     },
     "bind-obj-methods": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/bind-obj-methods/-/bind-obj-methods-2.0.1.tgz",
-      "integrity": "sha512-kKzUyCuc+jsWH4C2nW5KB2nh+rQRbQcdphfo9UN3j1uwIFGZ3JB8njtRZOiUAQCkxazH0nDQPN6x/zhvFcbZIw==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/bind-obj-methods/-/bind-obj-methods-3.0.0.tgz",
+      "integrity": "sha512-nLEaaz3/sEzNSyPWRsN9HNsqwk1AUyECtGj+XwGdIi3xABnEqecvXtIJ0wehQXuuER5uZ/5fTs2usONgYjG+iw==",
       "dev": true
     },
     "bindings": {
@@ -11659,28 +11710,15 @@
       }
     },
     "caching-transform": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz",
-      "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz",
+      "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==",
       "dev": true,
       "requires": {
-        "hasha": "^3.0.0",
-        "make-dir": "^2.0.0",
-        "package-hash": "^3.0.0",
-        "write-file-atomic": "^2.4.2"
-      },
-      "dependencies": {
-        "write-file-atomic": {
-          "version": "2.4.3",
-          "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
-          "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
-          "dev": true,
-          "requires": {
-            "graceful-fs": "^4.1.11",
-            "imurmurhash": "^0.1.4",
-            "signal-exit": "^3.0.2"
-          }
-        }
+        "hasha": "^5.0.0",
+        "make-dir": "^3.0.0",
+        "package-hash": "^4.0.0",
+        "write-file-atomic": "^3.0.0"
       }
     },
     "call-bind": {
@@ -11693,12 +11731,6 @@
         "get-intrinsic": "^1.0.2"
       }
     },
-    "caller": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/caller/-/caller-1.0.1.tgz",
-      "integrity": "sha1-uFGGD3Dhlds9J3OVqhp+I+ow7PU=",
-      "dev": true
-    },
     "callsites": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -12012,27 +12044,6 @@
         "request": "^2.88.2"
       }
     },
-    "cp-file": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz",
-      "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "^4.1.2",
-        "make-dir": "^2.0.0",
-        "nested-error-stacks": "^2.0.0",
-        "pify": "^4.0.1",
-        "safe-buffer": "^5.0.1"
-      },
-      "dependencies": {
-        "pify": {
-          "version": "4.0.1",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
-          "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
-          "dev": true
-        }
-      }
-    },
     "cross-spawn": {
       "version": "7.0.3",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -12140,12 +12151,20 @@
       "dev": true
     },
     "default-require-extensions": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz",
-      "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz",
+      "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==",
       "dev": true,
       "requires": {
-        "strip-bom": "^3.0.0"
+        "strip-bom": "^4.0.0"
+      },
+      "dependencies": {
+        "strip-bom": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+          "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+          "dev": true
+        }
       }
     },
     "defaults": {
@@ -12209,12 +12228,6 @@
       "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
       "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w=="
     },
-    "diff-frag": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/diff-frag/-/diff-frag-1.0.1.tgz",
-      "integrity": "sha512-6/v2PC/6UTGcWPPetb9acL8foberUg/CtPdALeJUdD1B/weHNvzftoo00gYznqHGRhHEbykUGzqfG9RWOSr5yw==",
-      "dev": true
-    },
     "docopt": {
       "version": "0.6.2",
       "resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz",
@@ -12422,9 +12435,9 @@
       }
     },
     "eslint": {
-      "version": "7.23.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.23.0.tgz",
-      "integrity": "sha512-kqvNVbdkjzpFy0XOszNwjkKzZ+6TcwCQ/h+ozlcIWwaimBBuhlQ4nN6kbiM2L+OjDcznkTJxzYfRFH92sx4a0Q==",
+      "version": "7.24.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz",
+      "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "7.12.11",
@@ -12482,9 +12495,9 @@
           "dev": true
         },
         "globals": {
-          "version": "13.7.0",
-          "resolved": "https://registry.npmjs.org/globals/-/globals-13.7.0.tgz",
-          "integrity": "sha512-Aipsz6ZKRxa/xQkZhNg0qIWXT6x6rD46f6x/PCnBomlttdIyAPak4YD9jTmKpZ72uROSMU87qJtcgpgHaVchiA==",
+          "version": "13.8.0",
+          "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz",
+          "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==",
           "dev": true,
           "requires": {
             "type-fest": "^0.20.2"
@@ -12693,12 +12706,6 @@
       "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
       "dev": true
     },
-    "esm": {
-      "version": "3.2.25",
-      "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
-      "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==",
-      "dev": true
-    },
     "espree": {
       "version": "7.3.1",
       "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
@@ -12833,33 +12840,33 @@
       }
     },
     "find-cache-dir": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
-      "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz",
+      "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==",
       "dev": true,
       "requires": {
         "commondir": "^1.0.1",
-        "make-dir": "^2.0.0",
-        "pkg-dir": "^3.0.0"
+        "make-dir": "^3.0.2",
+        "pkg-dir": "^4.1.0"
       },
       "dependencies": {
         "find-up": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
-          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+          "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
           "dev": true,
           "requires": {
-            "locate-path": "^3.0.0"
+            "locate-path": "^5.0.0",
+            "path-exists": "^4.0.0"
           }
         },
         "locate-path": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
-          "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+          "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
           "dev": true,
           "requires": {
-            "p-locate": "^3.0.0",
-            "path-exists": "^3.0.0"
+            "p-locate": "^4.1.0"
           }
         },
         "p-limit": {
@@ -12872,12 +12879,12 @@
           }
         },
         "p-locate": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
-          "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+          "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
           "dev": true,
           "requires": {
-            "p-limit": "^2.0.0"
+            "p-limit": "^2.2.0"
           }
         },
         "p-try": {
@@ -12886,13 +12893,19 @@
           "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
           "dev": true
         },
+        "path-exists": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+          "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+          "dev": true
+        },
         "pkg-dir": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
-          "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+          "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
           "dev": true,
           "requires": {
-            "find-up": "^3.0.0"
+            "find-up": "^4.0.0"
           }
         }
       }
@@ -12928,68 +12941,14 @@
       "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
       "dev": true
     },
-    "flow-parser": {
-      "version": "0.147.0",
-      "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.147.0.tgz",
-      "integrity": "sha512-z+b/pgp2QLvsWJkzhKXU8yC5TmaNyXGRmHac3x0Swmn9uQESRXhNIJq9TPHKPPeWgFym33OLO+5BlIdy/tXRCQ==",
-      "dev": true
-    },
-    "flow-remove-types": {
-      "version": "2.147.0",
-      "resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.147.0.tgz",
-      "integrity": "sha512-ppZdtui3daAhBe0dkghBdtdIdSRbc/p/IEXw3t6vtlbS2KNpY8G3cu5RupXT3pGvFQbbXHP7mwNCEKSEYGU6Aw==",
-      "dev": true,
-      "requires": {
-        "flow-parser": "^0.147.0",
-        "pirates": "^3.0.2",
-        "vlq": "^0.2.1"
-      }
-    },
     "foreground-child": {
-      "version": "1.5.6",
-      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz",
-      "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
+      "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==",
       "dev": true,
       "requires": {
-        "cross-spawn": "^4",
-        "signal-exit": "^3.0.0"
-      },
-      "dependencies": {
-        "cross-spawn": {
-          "version": "4.0.2",
-          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz",
-          "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=",
-          "dev": true,
-          "requires": {
-            "lru-cache": "^4.0.1",
-            "which": "^1.2.9"
-          }
-        },
-        "lru-cache": {
-          "version": "4.1.5",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
-          "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
-          "dev": true,
-          "requires": {
-            "pseudomap": "^1.0.2",
-            "yallist": "^2.1.2"
-          }
-        },
-        "which": {
-          "version": "1.3.1",
-          "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-          "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
-          "dev": true,
-          "requires": {
-            "isexe": "^2.0.0"
-          }
-        },
-        "yallist": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
-          "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
-          "dev": true
-        }
+        "cross-spawn": "^7.0.0",
+        "signal-exit": "^3.0.2"
       }
     },
     "forever-agent": {
@@ -13007,6 +12966,12 @@
         "mime-types": "^2.1.12"
       }
     },
+    "fromentries": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz",
+      "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==",
+      "dev": true
+    },
     "fs-access": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-2.0.0.tgz",
@@ -13054,9 +13019,9 @@
       "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
     },
     "function-loop": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/function-loop/-/function-loop-1.0.2.tgz",
-      "integrity": "sha512-Iw4MzMfS3udk/rqxTiDDCllhGwlOrsr50zViTOO/W6lS/9y6B1J0BD2VZzrnWUYBJsl3aeqjgR5v7bWWhZSYbA==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/function-loop/-/function-loop-2.0.1.tgz",
+      "integrity": "sha512-ktIR+O6i/4h+j/ZhZJNdzeI4i9lEPeEK6UPR2EVyTVBqOwcU3Za9xYKLH64ZR9HmcROyRrOkizNyjjtWJzDDkQ==",
       "dev": true
     },
     "functional-red-black-tree": {
@@ -13128,6 +13093,12 @@
         "has-symbols": "^1.0.1"
       }
     },
+    "get-package-type": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+      "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+      "dev": true
+    },
     "getpass": {
       "version": "0.1.7",
       "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
@@ -13220,12 +13191,13 @@
       "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
     },
     "hasha": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz",
-      "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=",
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
+      "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==",
       "dev": true,
       "requires": {
-        "is-stream": "^1.0.1"
+        "is-stream": "^2.0.0",
+        "type-fest": "^0.8.0"
       }
     },
     "hast-to-hyperscript": {
@@ -13624,9 +13596,9 @@
       "dev": true
     },
     "is-potential-custom-element-name": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz",
-      "integrity": "sha1-DFLlS8yjkbssSUsh6GJtczbG45c=",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+      "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
       "dev": true
     },
     "is-regex": {
@@ -13640,9 +13612,9 @@
       }
     },
     "is-stream": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
-      "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+      "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": {
@@ -13671,6 +13643,12 @@
       "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==",
       "dev": true
     },
+    "is-windows": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+      "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+      "dev": true
+    },
     "is-word-character": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz",
@@ -13693,33 +13671,30 @@
       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
     },
     "istanbul-lib-coverage": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
-      "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz",
+      "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==",
       "dev": true
     },
     "istanbul-lib-hook": {
-      "version": "2.0.7",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz",
-      "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz",
+      "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==",
       "dev": true,
       "requires": {
-        "append-transform": "^1.0.0"
+        "append-transform": "^2.0.0"
       }
     },
     "istanbul-lib-instrument": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
-      "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
+      "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
       "dev": true,
       "requires": {
-        "@babel/generator": "^7.4.0",
-        "@babel/parser": "^7.4.3",
-        "@babel/template": "^7.4.0",
-        "@babel/traverse": "^7.4.3",
-        "@babel/types": "^7.4.0",
-        "istanbul-lib-coverage": "^2.0.5",
-        "semver": "^6.0.0"
+        "@babel/core": "^7.7.5",
+        "@istanbuljs/schema": "^0.1.2",
+        "istanbul-lib-coverage": "^3.0.0",
+        "semver": "^6.3.0"
       },
       "dependencies": {
         "semver": {
@@ -13731,128 +13706,53 @@
       }
     },
     "istanbul-lib-processinfo": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-1.0.0.tgz",
-      "integrity": "sha512-FY0cPmWa4WoQNlvB8VOcafiRoB5nB+l2Pz2xGuXHRSy1KM8QFOYfz/rN+bGMCAeejrY3mrpF5oJHcN0s/garCg==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz",
+      "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==",
       "dev": true,
       "requires": {
         "archy": "^1.0.0",
-        "cross-spawn": "^6.0.5",
-        "istanbul-lib-coverage": "^2.0.3",
-        "rimraf": "^2.6.3",
-        "uuid": "^3.3.2"
+        "cross-spawn": "^7.0.0",
+        "istanbul-lib-coverage": "^3.0.0-alpha.1",
+        "make-dir": "^3.0.0",
+        "p-map": "^3.0.0",
+        "rimraf": "^3.0.0",
+        "uuid": "^3.3.3"
       },
       "dependencies": {
-        "cross-spawn": {
-          "version": "6.0.5",
-          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
-          "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
-          "dev": true,
-          "requires": {
-            "nice-try": "^1.0.4",
-            "path-key": "^2.0.1",
-            "semver": "^5.5.0",
-            "shebang-command": "^1.2.0",
-            "which": "^1.2.9"
-          }
-        },
-        "path-key": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
-          "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
-          "dev": true
-        },
-        "rimraf": {
-          "version": "2.7.1",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-          "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-          "dev": true,
-          "requires": {
-            "glob": "^7.1.3"
-          }
-        },
-        "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-          "dev": true
-        },
-        "shebang-command": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
-          "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
-          "dev": true,
-          "requires": {
-            "shebang-regex": "^1.0.0"
-          }
-        },
-        "shebang-regex": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
-          "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
-          "dev": true
-        },
-        "which": {
-          "version": "1.3.1",
-          "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-          "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+        "p-map": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
+          "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==",
           "dev": true,
           "requires": {
-            "isexe": "^2.0.0"
+            "aggregate-error": "^3.0.0"
           }
         }
       }
     },
     "istanbul-lib-report": {
-      "version": "2.0.8",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz",
-      "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
+      "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
       "dev": true,
       "requires": {
-        "istanbul-lib-coverage": "^2.0.5",
-        "make-dir": "^2.1.0",
-        "supports-color": "^6.1.0"
-      },
-      "dependencies": {
-        "has-flag": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-          "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "6.1.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
-          "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^3.0.0"
-          }
-        }
+        "istanbul-lib-coverage": "^3.0.0",
+        "make-dir": "^3.0.0",
+        "supports-color": "^7.1.0"
       }
     },
     "istanbul-lib-source-maps": {
-      "version": "3.0.6",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz",
-      "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz",
+      "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==",
       "dev": true,
       "requires": {
         "debug": "^4.1.1",
-        "istanbul-lib-coverage": "^2.0.5",
-        "make-dir": "^2.1.0",
-        "rimraf": "^2.6.3",
+        "istanbul-lib-coverage": "^3.0.0",
         "source-map": "^0.6.1"
       },
       "dependencies": {
-        "rimraf": {
-          "version": "2.7.1",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-          "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-          "dev": true,
-          "requires": {
-            "glob": "^7.1.3"
-          }
-        },
         "source-map": {
           "version": "0.6.1",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -13862,12 +13762,13 @@
       }
     },
     "istanbul-reports": {
-      "version": "2.2.7",
-      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz",
-      "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==",
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz",
+      "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==",
       "dev": true,
       "requires": {
-        "html-escaper": "^2.0.0"
+        "html-escaper": "^2.0.0",
+        "istanbul-lib-report": "^3.0.0"
       }
     },
     "jackspeak": {
@@ -13901,9 +13802,9 @@
       "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
     },
     "jsdom": {
-      "version": "16.5.2",
-      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.5.2.tgz",
-      "integrity": "sha512-JxNtPt9C1ut85boCbJmffaQ06NBnzkQY/MWO3YxPW8IWS38A26z+B1oBvA9LwKrytewdfymnhi4UNH3/RAgZrg==",
+      "version": "16.5.3",
+      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.5.3.tgz",
+      "integrity": "sha512-Qj1H+PEvUsOtdPJ056ewXM4UJPCi4hhLA8wpiz9F2YvsRBhuFsXxtrIFAgGBDynQA9isAMGE91PfUYbdMPXuTA==",
       "dev": true,
       "requires": {
         "abab": "^2.0.5",
@@ -13935,9 +13836,9 @@
       },
       "dependencies": {
         "acorn": {
-          "version": "8.1.0",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.1.0.tgz",
-          "integrity": "sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA==",
+          "version": "8.1.1",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.1.1.tgz",
+          "integrity": "sha512-xYiIVjNuqtKXMxlRMDc6mZUhXehod4a3gbZ1qRlM7icK4EbxUFNLhWoPblCvFtB2Y9CIqHP3CF/rdxLItaQv8g==",
           "dev": true
         }
       }
@@ -13948,12 +13849,6 @@
       "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
       "dev": true
     },
-    "json-parse-better-errors": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
-      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
-      "dev": true
-    },
     "json-parse-errback": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/json-parse-errback/-/json-parse-errback-2.0.1.tgz",
@@ -14017,9 +13912,9 @@
       }
     },
     "just-diff": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-3.0.2.tgz",
-      "integrity": "sha512-+EiNvacECnZbszZa5IMjzrJ3dy2HKMXyGaNYWBnXy+iWW+437jIvQUrWaM9M+XI/6gOH8EjqvhGUOSh7ETekyg=="
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-3.1.1.tgz",
+      "integrity": "sha512-sdMWKjRq8qWZEjDcVA6llnUT8RDEBIfOiGpYFPYa9u+2c39JCsejktSP7mj5eRid5EIvTzIpQ2kDOCw1Nq9BjQ=="
     },
     "just-diff-apply": {
       "version": "3.0.0",
@@ -14150,6 +14045,36 @@
         "stringify-package": "^1.0.1"
       }
     },
+    "libtap": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/libtap/-/libtap-1.1.1.tgz",
+      "integrity": "sha512-Fye8fh1+G7E8qqmjQaY+pXGxy7HM0S6bqCCJFLa16+g2jODBByxbJFDpjbDNF69wfRVyvJ+foLZc1WTIv7dx+g==",
+      "dev": true,
+      "requires": {
+        "async-hook-domain": "^2.0.1",
+        "bind-obj-methods": "^3.0.0",
+        "diff": "^4.0.2",
+        "function-loop": "^2.0.1",
+        "minipass": "^3.1.1",
+        "own-or": "^1.0.0",
+        "own-or-env": "^1.0.1",
+        "signal-exit": "^3.0.2",
+        "stack-utils": "^2.0.1",
+        "tap-parser": "^10.0.1",
+        "tap-yaml": "^1.0.0",
+        "tcompare": "^5.0.1",
+        "trivial-deferred": "^1.0.1",
+        "yapool": "^1.0.0"
+      },
+      "dependencies": {
+        "diff": {
+          "version": "4.0.2",
+          "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+          "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+          "dev": true
+        }
+      }
+    },
     "licensee": {
       "version": "8.2.0",
       "resolved": "https://registry.npmjs.org/licensee/-/licensee-8.2.0.tgz",
@@ -14209,12 +14134,30 @@
       "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
       "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.flatten": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+      "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
+      "dev": true
+    },
     "lodash.flattendeep": {
       "version": "4.4.0",
       "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
       "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
       "dev": true
     },
+    "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.uniq": {
       "version": "4.5.0",
       "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@@ -14245,35 +14188,22 @@
       }
     },
     "make-dir": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
-      "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+      "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
       "dev": true,
       "requires": {
-        "pify": "^4.0.1",
-        "semver": "^5.6.0"
+        "semver": "^6.0.0"
       },
       "dependencies": {
-        "pify": {
-          "version": "4.0.1",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
-          "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
-          "dev": true
-        },
         "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
           "dev": true
         }
       }
     },
-    "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
-    },
     "make-fetch-happen": {
       "version": "8.0.14",
       "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz",
@@ -14356,34 +14286,17 @@
       "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
       "dev": true
     },
-    "merge-source-map": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz",
-      "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==",
-      "dev": true,
-      "requires": {
-        "source-map": "^0.6.1"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "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.47.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz",
+      "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw=="
     },
     "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==",
+      "version": "2.1.30",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz",
+      "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==",
       "requires": {
-        "mime-db": "1.46.0"
+        "mime-db": "1.47.0"
       }
     },
     "mimic-response": {
@@ -14518,18 +14431,6 @@
       "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
       "dev": true
     },
-    "nested-error-stacks": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz",
-      "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==",
-      "dev": true
-    },
-    "nice-try": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
-      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
-      "dev": true
-    },
     "node-abi": {
       "version": "2.21.0",
       "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.21.0.tgz",
@@ -14570,11 +14471,14 @@
         "which": "^2.0.2"
       }
     },
-    "node-modules-regexp": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz",
-      "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=",
-      "dev": true
+    "node-preload": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
+      "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==",
+      "dev": true,
+      "requires": {
+        "process-on-spawn": "^1.0.0"
+      }
     },
     "noop-logger": {
       "version": "0.1.1",
@@ -14731,55 +14635,57 @@
       "dev": true
     },
     "nyc": {
-      "version": "14.1.1",
-      "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz",
-      "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==",
+      "version": "15.1.0",
+      "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz",
+      "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==",
       "dev": true,
       "requires": {
-        "archy": "^1.0.0",
-        "caching-transform": "^3.0.2",
-        "convert-source-map": "^1.6.0",
-        "cp-file": "^6.2.0",
-        "find-cache-dir": "^2.1.0",
-        "find-up": "^3.0.0",
-        "foreground-child": "^1.5.6",
-        "glob": "^7.1.3",
-        "istanbul-lib-coverage": "^2.0.5",
-        "istanbul-lib-hook": "^2.0.7",
-        "istanbul-lib-instrument": "^3.3.0",
-        "istanbul-lib-report": "^2.0.8",
-        "istanbul-lib-source-maps": "^3.0.6",
-        "istanbul-reports": "^2.2.4",
-        "js-yaml": "^3.13.1",
-        "make-dir": "^2.1.0",
-        "merge-source-map": "^1.1.0",
-        "resolve-from": "^4.0.0",
-        "rimraf": "^2.6.3",
+        "@istanbuljs/load-nyc-config": "^1.0.0",
+        "@istanbuljs/schema": "^0.1.2",
+        "caching-transform": "^4.0.0",
+        "convert-source-map": "^1.7.0",
+        "decamelize": "^1.2.0",
+        "find-cache-dir": "^3.2.0",
+        "find-up": "^4.1.0",
+        "foreground-child": "^2.0.0",
+        "get-package-type": "^0.1.0",
+        "glob": "^7.1.6",
+        "istanbul-lib-coverage": "^3.0.0",
+        "istanbul-lib-hook": "^3.0.0",
+        "istanbul-lib-instrument": "^4.0.0",
+        "istanbul-lib-processinfo": "^2.0.2",
+        "istanbul-lib-report": "^3.0.0",
+        "istanbul-lib-source-maps": "^4.0.0",
+        "istanbul-reports": "^3.0.2",
+        "make-dir": "^3.0.0",
+        "node-preload": "^0.2.1",
+        "p-map": "^3.0.0",
+        "process-on-spawn": "^1.0.0",
+        "resolve-from": "^5.0.0",
+        "rimraf": "^3.0.0",
         "signal-exit": "^3.0.2",
-        "spawn-wrap": "^1.4.2",
-        "test-exclude": "^5.2.3",
-        "uuid": "^3.3.2",
-        "yargs": "^13.2.2",
-        "yargs-parser": "^13.0.0"
+        "spawn-wrap": "^2.0.0",
+        "test-exclude": "^6.0.0",
+        "yargs": "^15.0.2"
       },
       "dependencies": {
         "find-up": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
-          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+          "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
           "dev": true,
           "requires": {
-            "locate-path": "^3.0.0"
+            "locate-path": "^5.0.0",
+            "path-exists": "^4.0.0"
           }
         },
         "locate-path": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
-          "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+          "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
           "dev": true,
           "requires": {
-            "p-locate": "^3.0.0",
-            "path-exists": "^3.0.0"
+            "p-locate": "^4.1.0"
           }
         },
         "p-limit": {
@@ -14792,12 +14698,21 @@
           }
         },
         "p-locate": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+          "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+          "dev": true,
+          "requires": {
+            "p-limit": "^2.2.0"
+          }
+        },
+        "p-map": {
           "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
-          "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+          "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
+          "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==",
           "dev": true,
           "requires": {
-            "p-limit": "^2.0.0"
+            "aggregate-error": "^3.0.0"
           }
         },
         "p-try": {
@@ -14806,14 +14721,17 @@
           "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
           "dev": true
         },
-        "rimraf": {
-          "version": "2.7.1",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-          "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-          "dev": true,
-          "requires": {
-            "glob": "^7.1.3"
-          }
+        "path-exists": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+          "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+          "dev": true
+        },
+        "resolve-from": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+          "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+          "dev": true
         }
       }
     },
@@ -14901,12 +14819,6 @@
         "word-wrap": "^1.2.3"
       }
     },
-    "os-homedir": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
-      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
-      "dev": true
-    },
     "own-or": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/own-or/-/own-or-1.0.0.tgz",
@@ -14955,13 +14867,13 @@
       "dev": true
     },
     "package-hash": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz",
-      "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz",
+      "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==",
       "dev": true,
       "requires": {
         "graceful-fs": "^4.1.15",
-        "hasha": "^3.0.0",
+        "hasha": "^5.0.0",
         "lodash.flattendeep": "^4.4.0",
         "release-zalgo": "^1.0.0"
       }
@@ -15077,9 +14989,9 @@
       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
     },
     "picomatch": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
-      "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz",
+      "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==",
       "dev": true
     },
     "pify": {
@@ -15088,15 +15000,6 @@
       "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
       "dev": true
     },
-    "pirates": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/pirates/-/pirates-3.0.2.tgz",
-      "integrity": "sha512-c5CgUJq6H2k6MJz72Ak1F5sN9n9wlSlJyEnwvpm9/y3WB4E3pHBDT2c6PEiS1vyJvq2bUxUAIu0EGf8Cx4Ic7Q==",
-      "dev": true,
-      "requires": {
-        "node-modules-regexp": "^1.0.0"
-      }
-    },
     "pkg-dir": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
@@ -15107,9 +15010,9 @@
       }
     },
     "prebuild-install": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.0.1.tgz",
-      "integrity": "sha512-7GOJrLuow8yeiyv75rmvZyeMGzl8mdEX5gY69d6a6bHWmiPevwqFw+tQavhK0EYMaSg3/KD24cWqeQv1EWsqDQ==",
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.1.tgz",
+      "integrity": "sha512-M+cKwofFlHa5VpTWub7GLg5RLcunYIcLqtY5pKcls/u7xaAb8FrXZ520qY8rkpYy5xw90tYCyMO0MP5ggzR3Sw==",
       "dev": true,
       "requires": {
         "detect-libc": "^1.0.3",
@@ -15118,15 +15021,14 @@
         "minimist": "^1.2.3",
         "mkdirp-classic": "^0.5.3",
         "napi-build-utils": "^1.0.1",
-        "node-abi": "^2.7.0",
+        "node-abi": "^2.21.0",
         "noop-logger": "^0.1.1",
         "npmlog": "^4.0.1",
         "pump": "^3.0.0",
         "rc": "^1.2.7",
         "simple-get": "^3.0.3",
         "tar-fs": "^2.0.0",
-        "tunnel-agent": "^0.6.0",
-        "which-pm-runs": "^1.0.0"
+        "tunnel-agent": "^0.6.0"
       }
     },
     "prelude-ls": {
@@ -15140,6 +15042,15 @@
       "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
       "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
     },
+    "process-on-spawn": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz",
+      "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==",
+      "dev": true,
+      "requires": {
+        "fromentries": "^1.2.0"
+      }
+    },
     "progress": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
@@ -15198,12 +15109,6 @@
         "xtend": "^4.0.0"
       }
     },
-    "pseudomap": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
-      "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
-      "dev": true
-    },
     "psl": {
       "version": "1.8.0",
       "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
@@ -15328,9 +15233,9 @@
       },
       "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": {
@@ -15377,9 +15282,9 @@
       },
       "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": {
@@ -15612,15 +15517,6 @@
       "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
       "dev": true
     },
-    "require-inject": {
-      "version": "1.4.4",
-      "resolved": "https://registry.npmjs.org/require-inject/-/require-inject-1.4.4.tgz",
-      "integrity": "sha512-5Y5ctRN84+I4iOZO61gm+48tgP/6Hcd3VZydkaEM3MCuOvnHRsTJYQBOc01faI/Z9at5nsCAJVHhlfPA6Pc0Og==",
-      "dev": true,
-      "requires": {
-        "caller": "^1.0.1"
-      }
-    },
     "require-main-filename": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
@@ -15807,46 +15703,17 @@
       "dev": true
     },
     "spawn-wrap": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz",
-      "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz",
+      "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==",
       "dev": true,
       "requires": {
-        "foreground-child": "^1.5.6",
-        "mkdirp": "^0.5.0",
-        "os-homedir": "^1.0.1",
-        "rimraf": "^2.6.2",
+        "foreground-child": "^2.0.0",
+        "is-windows": "^1.0.2",
+        "make-dir": "^3.0.0",
+        "rimraf": "^3.0.0",
         "signal-exit": "^3.0.2",
-        "which": "^1.3.0"
-      },
-      "dependencies": {
-        "mkdirp": {
-          "version": "0.5.5",
-          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
-          "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
-          "dev": true,
-          "requires": {
-            "minimist": "^1.2.5"
-          }
-        },
-        "rimraf": {
-          "version": "2.7.1",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-          "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-          "dev": true,
-          "requires": {
-            "glob": "^7.1.3"
-          }
-        },
-        "which": {
-          "version": "1.3.1",
-          "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-          "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
-          "dev": true,
-          "requires": {
-            "isexe": "^2.0.0"
-          }
-        }
+        "which": "^2.0.1"
       }
     },
     "spdx-compare": {
@@ -15950,9 +15817,9 @@
       }
     },
     "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": "2.0.3",
+      "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz",
+      "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==",
       "dev": true,
       "requires": {
         "escape-string-regexp": "^2.0.0"
@@ -16071,21 +15938,26 @@
       "dev": true
     },
     "table": {
-      "version": "6.0.7",
-      "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz",
-      "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==",
+      "version": "6.0.9",
+      "resolved": "https://registry.npmjs.org/table/-/table-6.0.9.tgz",
+      "integrity": "sha512-F3cLs9a3hL1Z7N4+EkSscsel3z55XT950AvB05bwayrNg5T1/gykXtigioTAjbltvbMSJvvhFCbnf6mX+ntnJQ==",
       "dev": true,
       "requires": {
-        "ajv": "^7.0.2",
-        "lodash": "^4.17.20",
+        "ajv": "^8.0.1",
+        "is-boolean-object": "^1.1.0",
+        "is-number-object": "^1.0.4",
+        "is-string": "^1.0.5",
+        "lodash.clonedeep": "^4.5.0",
+        "lodash.flatten": "^4.4.0",
+        "lodash.truncate": "^4.4.2",
         "slice-ansi": "^4.0.0",
         "string-width": "^4.2.0"
       },
       "dependencies": {
         "ajv": {
-          "version": "7.2.3",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.2.3.tgz",
-          "integrity": "sha512-idv5WZvKVXDqKralOImQgPM9v6WOdLNa0IY3B3doOjw/YxRGT8I+allIJ6kd7Uaj+SF1xZUSU+nPM5aDNBVtnw==",
+          "version": "8.1.0",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz",
+          "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==",
           "dev": true,
           "requires": {
             "fast-deep-equal": "^3.1.1",
@@ -16135,273 +16007,246 @@
       }
     },
     "tap": {
-      "version": "14.11.0",
-      "resolved": "https://registry.npmjs.org/tap/-/tap-14.11.0.tgz",
-      "integrity": "sha512-z8qnNFVyIjLh/bNoTLFRkEk09XZUDAZbCkz/BjvHHly3ao5H+y60gPnedALfheEjA6dA4tpp/mrKq2NWlMuq0A==",
+      "version": "15.0.2",
+      "resolved": "https://registry.npmjs.org/tap/-/tap-15.0.2.tgz",
+      "integrity": "sha512-HfEahBCFIA/t3YuBZxkgfu9UiLqpOo/ibCs1xgGwJSWNqdmIxF8tiPwmgni+7SlNtmf0jNfYjT2xeatfZ7t/QA==",
       "dev": true,
       "requires": {
-        "@types/react": "^16.9.16",
-        "async-hook-domain": "^1.1.3",
-        "bind-obj-methods": "^2.0.0",
-        "browser-process-hrtime": "^1.0.0",
+        "@types/react": "^16.9.23",
         "chokidar": "^3.3.0",
-        "color-support": "^1.1.0",
         "coveralls": "^3.0.11",
-        "diff": "^4.0.1",
-        "esm": "^3.2.25",
         "findit": "^2.0.0",
-        "flow-remove-types": "^2.112.0",
-        "foreground-child": "^1.3.3",
+        "foreground-child": "^2.0.0",
         "fs-exists-cached": "^1.0.0",
-        "function-loop": "^1.0.2",
         "glob": "^7.1.6",
-        "import-jsx": "^3.1.0",
-        "ink": "^2.6.0",
+        "import-jsx": "^4.0.0",
+        "ink": "^2.7.1",
         "isexe": "^2.0.0",
-        "istanbul-lib-processinfo": "^1.0.0",
+        "istanbul-lib-processinfo": "^2.0.2",
         "jackspeak": "^1.4.0",
+        "libtap": "^1.1.1",
         "minipass": "^3.1.1",
-        "mkdirp": "^0.5.4",
-        "nyc": "^14.1.1",
+        "mkdirp": "^1.0.4",
+        "nyc": "^15.1.0",
         "opener": "^1.5.1",
-        "own-or": "^1.0.0",
-        "own-or-env": "^1.0.1",
         "react": "^16.12.0",
-        "rimraf": "^2.7.1",
+        "rimraf": "^3.0.0",
         "signal-exit": "^3.0.0",
         "source-map-support": "^0.5.16",
-        "stack-utils": "^1.0.3",
         "tap-mocha-reporter": "^5.0.0",
         "tap-parser": "^10.0.1",
         "tap-yaml": "^1.0.0",
-        "tcompare": "^3.0.0",
-        "treport": "^1.0.2",
-        "trivial-deferred": "^1.0.1",
-        "ts-node": "^8.5.2",
-        "typescript": "^3.7.2",
-        "which": "^2.0.2",
-        "write-file-atomic": "^3.0.1",
-        "yaml": "^1.7.2",
-        "yapool": "^1.0.0"
+        "tcompare": "^5.0.4",
+        "treport": "^2.0.0",
+        "which": "^2.0.2"
       },
       "dependencies": {
         "@babel/code-frame": {
-          "version": "7.10.4",
+          "version": "7.12.13",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/highlight": "^7.10.4"
+            "@babel/highlight": "^7.12.13"
           }
         },
+        "@babel/compat-data": {
+          "version": "7.13.12",
+          "bundled": true,
+          "dev": true
+        },
         "@babel/core": {
-          "version": "7.10.5",
+          "version": "7.13.14",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/code-frame": "^7.10.4",
-            "@babel/generator": "^7.10.5",
-            "@babel/helper-module-transforms": "^7.10.5",
-            "@babel/helpers": "^7.10.4",
-            "@babel/parser": "^7.10.5",
-            "@babel/template": "^7.10.4",
-            "@babel/traverse": "^7.10.5",
-            "@babel/types": "^7.10.5",
+            "@babel/code-frame": "^7.12.13",
+            "@babel/generator": "^7.13.9",
+            "@babel/helper-compilation-targets": "^7.13.13",
+            "@babel/helper-module-transforms": "^7.13.14",
+            "@babel/helpers": "^7.13.10",
+            "@babel/parser": "^7.13.13",
+            "@babel/template": "^7.12.13",
+            "@babel/traverse": "^7.13.13",
+            "@babel/types": "^7.13.14",
             "convert-source-map": "^1.7.0",
             "debug": "^4.1.0",
-            "gensync": "^1.0.0-beta.1",
+            "gensync": "^1.0.0-beta.2",
             "json5": "^2.1.2",
-            "lodash": "^4.17.19",
-            "resolve": "^1.3.2",
-            "semver": "^5.4.1",
+            "semver": "^6.3.0",
             "source-map": "^0.5.0"
-          },
-          "dependencies": {
-            "source-map": {
-              "version": "0.5.7",
-              "bundled": true,
-              "dev": true
-            }
           }
         },
         "@babel/generator": {
-          "version": "7.10.5",
+          "version": "7.13.9",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/types": "^7.10.5",
+            "@babel/types": "^7.13.0",
             "jsesc": "^2.5.1",
             "source-map": "^0.5.0"
-          },
-          "dependencies": {
-            "source-map": {
-              "version": "0.5.7",
-              "bundled": true,
-              "dev": true
-            }
           }
         },
         "@babel/helper-annotate-as-pure": {
-          "version": "7.10.4",
-          "bundled": true,
-          "dev": true,
-          "requires": {
-            "@babel/types": "^7.10.4"
-          }
-        },
-        "@babel/helper-builder-react-jsx": {
-          "version": "7.10.4",
+          "version": "7.12.13",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/helper-annotate-as-pure": "^7.10.4",
-            "@babel/types": "^7.10.4"
+            "@babel/types": "^7.12.13"
           }
         },
-        "@babel/helper-builder-react-jsx-experimental": {
-          "version": "7.10.5",
+        "@babel/helper-compilation-targets": {
+          "version": "7.13.13",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/helper-annotate-as-pure": "^7.10.4",
-            "@babel/helper-module-imports": "^7.10.4",
-            "@babel/types": "^7.10.5"
+            "@babel/compat-data": "^7.13.12",
+            "@babel/helper-validator-option": "^7.12.17",
+            "browserslist": "^4.14.5",
+            "semver": "^6.3.0"
           }
         },
         "@babel/helper-function-name": {
-          "version": "7.10.4",
+          "version": "7.12.13",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/helper-get-function-arity": "^7.10.4",
-            "@babel/template": "^7.10.4",
-            "@babel/types": "^7.10.4"
+            "@babel/helper-get-function-arity": "^7.12.13",
+            "@babel/template": "^7.12.13",
+            "@babel/types": "^7.12.13"
           }
         },
         "@babel/helper-get-function-arity": {
-          "version": "7.10.4",
+          "version": "7.12.13",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/types": "^7.10.4"
+            "@babel/types": "^7.12.13"
           }
         },
         "@babel/helper-member-expression-to-functions": {
-          "version": "7.10.5",
+          "version": "7.13.12",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/types": "^7.10.5"
+            "@babel/types": "^7.13.12"
           }
         },
         "@babel/helper-module-imports": {
-          "version": "7.10.4",
+          "version": "7.13.12",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/types": "^7.10.4"
+            "@babel/types": "^7.13.12"
           }
         },
         "@babel/helper-module-transforms": {
-          "version": "7.10.5",
+          "version": "7.13.14",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/helper-module-imports": "^7.10.4",
-            "@babel/helper-replace-supers": "^7.10.4",
-            "@babel/helper-simple-access": "^7.10.4",
-            "@babel/helper-split-export-declaration": "^7.10.4",
-            "@babel/template": "^7.10.4",
-            "@babel/types": "^7.10.5",
-            "lodash": "^4.17.19"
+            "@babel/helper-module-imports": "^7.13.12",
+            "@babel/helper-replace-supers": "^7.13.12",
+            "@babel/helper-simple-access": "^7.13.12",
+            "@babel/helper-split-export-declaration": "^7.12.13",
+            "@babel/helper-validator-identifier": "^7.12.11",
+            "@babel/template": "^7.12.13",
+            "@babel/traverse": "^7.13.13",
+            "@babel/types": "^7.13.14"
           }
         },
         "@babel/helper-optimise-call-expression": {
-          "version": "7.10.4",
+          "version": "7.12.13",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/types": "^7.10.4"
+            "@babel/types": "^7.12.13"
           }
         },
         "@babel/helper-plugin-utils": {
-          "version": "7.10.4",
+          "version": "7.13.0",
           "bundled": true,
           "dev": true
         },
         "@babel/helper-replace-supers": {
-          "version": "7.10.4",
+          "version": "7.13.12",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/helper-member-expression-to-functions": "^7.10.4",
-            "@babel/helper-optimise-call-expression": "^7.10.4",
-            "@babel/traverse": "^7.10.4",
-            "@babel/types": "^7.10.4"
+            "@babel/helper-member-expression-to-functions": "^7.13.12",
+            "@babel/helper-optimise-call-expression": "^7.12.13",
+            "@babel/traverse": "^7.13.0",
+            "@babel/types": "^7.13.12"
           }
         },
         "@babel/helper-simple-access": {
-          "version": "7.10.4",
+          "version": "7.13.12",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/template": "^7.10.4",
-            "@babel/types": "^7.10.4"
+            "@babel/types": "^7.13.12"
           }
         },
         "@babel/helper-split-export-declaration": {
-          "version": "7.10.4",
+          "version": "7.12.13",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/types": "^7.10.4"
+            "@babel/types": "^7.12.13"
           }
         },
         "@babel/helper-validator-identifier": {
-          "version": "7.10.4",
+          "version": "7.12.11",
+          "bundled": true,
+          "dev": true
+        },
+        "@babel/helper-validator-option": {
+          "version": "7.12.17",
           "bundled": true,
           "dev": true
         },
         "@babel/helpers": {
-          "version": "7.10.4",
+          "version": "7.13.10",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/template": "^7.10.4",
-            "@babel/traverse": "^7.10.4",
-            "@babel/types": "^7.10.4"
+            "@babel/template": "^7.12.13",
+            "@babel/traverse": "^7.13.0",
+            "@babel/types": "^7.13.0"
           }
         },
         "@babel/highlight": {
-          "version": "7.10.4",
+          "version": "7.13.10",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
+            "@babel/helper-validator-identifier": "^7.12.11",
             "chalk": "^2.0.0",
             "js-tokens": "^4.0.0"
           }
         },
         "@babel/parser": {
-          "version": "7.10.5",
+          "version": "7.13.13",
           "bundled": true,
           "dev": true
         },
         "@babel/plugin-proposal-object-rest-spread": {
-          "version": "7.10.4",
+          "version": "7.13.8",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/helper-plugin-utils": "^7.10.4",
-            "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
-            "@babel/plugin-transform-parameters": "^7.10.4"
+            "@babel/compat-data": "^7.13.8",
+            "@babel/helper-compilation-targets": "^7.13.8",
+            "@babel/helper-plugin-utils": "^7.13.0",
+            "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+            "@babel/plugin-transform-parameters": "^7.13.0"
           }
         },
         "@babel/plugin-syntax-jsx": {
-          "version": "7.10.4",
+          "version": "7.12.13",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/helper-plugin-utils": "^7.10.4"
+            "@babel/helper-plugin-utils": "^7.12.13"
           }
         },
         "@babel/plugin-syntax-object-rest-spread": {
@@ -16413,106 +16258,101 @@
           }
         },
         "@babel/plugin-transform-destructuring": {
-          "version": "7.10.4",
+          "version": "7.13.0",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/helper-plugin-utils": "^7.10.4"
+            "@babel/helper-plugin-utils": "^7.13.0"
           }
         },
         "@babel/plugin-transform-parameters": {
-          "version": "7.10.5",
+          "version": "7.13.0",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/helper-get-function-arity": "^7.10.4",
-            "@babel/helper-plugin-utils": "^7.10.4"
+            "@babel/helper-plugin-utils": "^7.13.0"
           }
         },
         "@babel/plugin-transform-react-jsx": {
-          "version": "7.10.4",
+          "version": "7.13.12",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/helper-builder-react-jsx": "^7.10.4",
-            "@babel/helper-builder-react-jsx-experimental": "^7.10.4",
-            "@babel/helper-plugin-utils": "^7.10.4",
-            "@babel/plugin-syntax-jsx": "^7.10.4"
+            "@babel/helper-annotate-as-pure": "^7.12.13",
+            "@babel/helper-module-imports": "^7.13.12",
+            "@babel/helper-plugin-utils": "^7.13.0",
+            "@babel/plugin-syntax-jsx": "^7.12.13",
+            "@babel/types": "^7.13.12"
           }
         },
         "@babel/template": {
-          "version": "7.10.4",
+          "version": "7.12.13",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/code-frame": "^7.10.4",
-            "@babel/parser": "^7.10.4",
-            "@babel/types": "^7.10.4"
+            "@babel/code-frame": "^7.12.13",
+            "@babel/parser": "^7.12.13",
+            "@babel/types": "^7.12.13"
           }
         },
         "@babel/traverse": {
-          "version": "7.10.5",
+          "version": "7.13.13",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/code-frame": "^7.10.4",
-            "@babel/generator": "^7.10.5",
-            "@babel/helper-function-name": "^7.10.4",
-            "@babel/helper-split-export-declaration": "^7.10.4",
-            "@babel/parser": "^7.10.5",
-            "@babel/types": "^7.10.5",
+            "@babel/code-frame": "^7.12.13",
+            "@babel/generator": "^7.13.9",
+            "@babel/helper-function-name": "^7.12.13",
+            "@babel/helper-split-export-declaration": "^7.12.13",
+            "@babel/parser": "^7.13.13",
+            "@babel/types": "^7.13.13",
             "debug": "^4.1.0",
-            "globals": "^11.1.0",
-            "lodash": "^4.17.19"
+            "globals": "^11.1.0"
           }
         },
         "@babel/types": {
-          "version": "7.10.5",
+          "version": "7.13.14",
           "bundled": true,
           "dev": true,
           "requires": {
-            "@babel/helper-validator-identifier": "^7.10.4",
+            "@babel/helper-validator-identifier": "^7.12.11",
             "lodash": "^4.17.19",
             "to-fast-properties": "^2.0.0"
           }
         },
-        "@types/color-name": {
-          "version": "1.1.1",
-          "bundled": true,
-          "dev": true
-        },
         "@types/prop-types": {
           "version": "15.7.3",
           "bundled": true,
           "dev": true
         },
         "@types/react": {
-          "version": "16.9.43",
+          "version": "16.14.5",
           "bundled": true,
           "dev": true,
           "requires": {
             "@types/prop-types": "*",
-            "csstype": "^2.2.0"
+            "@types/scheduler": "*",
+            "csstype": "^3.0.2"
           }
         },
+        "@types/scheduler": {
+          "version": "0.16.1",
+          "bundled": true,
+          "dev": true
+        },
         "@types/yoga-layout": {
           "version": "1.9.2",
           "bundled": true,
           "dev": true
         },
         "ansi-escapes": {
-          "version": "4.3.1",
+          "version": "4.3.2",
           "bundled": true,
           "dev": true,
           "requires": {
-            "type-fest": "^0.11.0"
+            "type-fest": "^0.21.3"
           }
         },
-        "ansi-regex": {
-          "version": "5.0.0",
-          "bundled": true,
-          "dev": true
-        },
         "ansi-styles": {
           "version": "3.2.1",
           "bundled": true,
@@ -16541,6 +16381,32 @@
           "bundled": true,
           "dev": true
         },
+        "balanced-match": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "brace-expansion": {
+          "version": "1.1.11",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
+        "browserslist": {
+          "version": "4.16.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "caniuse-lite": "^1.0.30001181",
+            "colorette": "^1.2.1",
+            "electron-to-chromium": "^1.3.649",
+            "escalade": "^3.1.1",
+            "node-releases": "^1.1.70"
+          }
+        },
         "caller-callsite": {
           "version": "2.0.0",
           "bundled": true,
@@ -16562,6 +16428,11 @@
           "bundled": true,
           "dev": true
         },
+        "caniuse-lite": {
+          "version": "1.0.30001204",
+          "bundled": true,
+          "dev": true
+        },
         "cardinal": {
           "version": "2.1.1",
           "bundled": true,
@@ -16616,38 +16487,45 @@
           "bundled": true,
           "dev": true
         },
+        "colorette": {
+          "version": "1.2.2",
+          "bundled": true,
+          "dev": true
+        },
+        "commondir": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "concat-map": {
+          "version": "0.0.1",
+          "bundled": true,
+          "dev": true
+        },
         "convert-source-map": {
           "version": "1.7.0",
           "bundled": true,
           "dev": true,
           "requires": {
             "safe-buffer": "~5.1.1"
-          },
-          "dependencies": {
-            "safe-buffer": {
-              "version": "5.1.2",
-              "bundled": true,
-              "dev": true
-            }
           }
         },
         "csstype": {
-          "version": "2.6.11",
+          "version": "3.0.7",
           "bundled": true,
           "dev": true
         },
         "debug": {
-          "version": "4.1.1",
+          "version": "4.3.1",
           "bundled": true,
           "dev": true,
           "requires": {
-            "ms": "^2.1.1"
+            "ms": "2.1.2"
           }
         },
-        "diff": {
-          "version": "4.0.2",
-          "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
-          "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+        "electron-to-chromium": {
+          "version": "1.3.703",
+          "bundled": true,
           "dev": true
         },
         "emoji-regex": {
@@ -16655,6 +16533,11 @@
           "bundled": true,
           "dev": true
         },
+        "escalade": {
+          "version": "3.1.1",
+          "bundled": true,
+          "dev": true
+        },
         "escape-string-regexp": {
           "version": "1.0.5",
           "bundled": true,
@@ -16670,11 +16553,48 @@
           "bundled": true,
           "dev": true
         },
+        "find-cache-dir": {
+          "version": "3.3.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "commondir": "^1.0.1",
+            "make-dir": "^3.0.2",
+            "pkg-dir": "^4.1.0"
+          }
+        },
+        "find-up": {
+          "version": "4.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "locate-path": "^5.0.0",
+            "path-exists": "^4.0.0"
+          }
+        },
+        "fs.realpath": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
         "gensync": {
-          "version": "1.0.0-beta.1",
+          "version": "1.0.0-beta.2",
           "bundled": true,
           "dev": true
         },
+        "glob": {
+          "version": "7.1.6",
+          "bundled": true,
+          "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"
+          }
+        },
         "globals": {
           "version": "11.12.0",
           "bundled": true,
@@ -16686,7 +16606,7 @@
           "dev": true
         },
         "import-jsx": {
-          "version": "3.1.0",
+          "version": "4.0.0",
           "bundled": true,
           "dev": true,
           "requires": {
@@ -16695,9 +16615,26 @@
             "@babel/plugin-transform-destructuring": "^7.5.0",
             "@babel/plugin-transform-react-jsx": "^7.3.0",
             "caller-path": "^2.0.0",
-            "resolve-from": "^3.0.0"
+            "find-cache-dir": "^3.2.0",
+            "make-dir": "^3.0.2",
+            "resolve-from": "^3.0.0",
+            "rimraf": "^3.0.0"
+          }
+        },
+        "inflight": {
+          "version": "1.0.6",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "once": "^1.3.0",
+            "wrappy": "1"
           }
         },
+        "inherits": {
+          "version": "2.0.4",
+          "bundled": true,
+          "dev": true
+        },
         "ink": {
           "version": "2.7.1",
           "bundled": true,
@@ -16724,11 +16661,10 @@
           },
           "dependencies": {
             "ansi-styles": {
-              "version": "4.2.1",
+              "version": "4.3.0",
               "bundled": true,
               "dev": true,
               "requires": {
-                "@types/color-name": "^1.1.1",
                 "color-convert": "^2.0.1"
               }
             },
@@ -16760,7 +16696,7 @@
               "dev": true
             },
             "supports-color": {
-              "version": "7.1.0",
+              "version": "7.2.0",
               "bundled": true,
               "dev": true,
               "requires": {
@@ -16793,15 +16729,23 @@
           "dev": true
         },
         "json5": {
-          "version": "2.1.3",
+          "version": "2.2.0",
           "bundled": true,
           "dev": true,
           "requires": {
             "minimist": "^1.2.5"
           }
         },
+        "locate-path": {
+          "version": "5.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "p-locate": "^4.1.0"
+          }
+        },
         "lodash": {
-          "version": "4.17.19",
+          "version": "4.17.21",
           "bundled": true,
           "dev": true
         },
@@ -16908,11 +16852,27 @@
             "js-tokens": "^3.0.0 || ^4.0.0"
           }
         },
+        "make-dir": {
+          "version": "3.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "semver": "^6.0.0"
+          }
+        },
         "mimic-fn": {
           "version": "2.1.0",
           "bundled": true,
           "dev": true
         },
+        "minimatch": {
+          "version": "3.0.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        },
         "minimist": {
           "version": "1.2.5",
           "bundled": true,
@@ -16924,22 +16884,6 @@
           "dev": true,
           "requires": {
             "yallist": "^4.0.0"
-          },
-          "dependencies": {
-            "yallist": {
-              "version": "4.0.0",
-              "bundled": true,
-              "dev": true
-            }
-          }
-        },
-        "mkdirp": {
-          "version": "0.5.5",
-          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
-          "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
-          "dev": true,
-          "requires": {
-            "minimist": "^1.2.5"
           }
         },
         "ms": {
@@ -16947,24 +16891,71 @@
           "bundled": true,
           "dev": true
         },
+        "node-releases": {
+          "version": "1.1.71",
+          "bundled": true,
+          "dev": true
+        },
         "object-assign": {
           "version": "4.1.1",
           "bundled": true,
           "dev": true
         },
+        "once": {
+          "version": "1.4.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "wrappy": "1"
+          }
+        },
         "onetime": {
-          "version": "5.1.0",
+          "version": "5.1.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "mimic-fn": "^2.1.0"
+          }
+        },
+        "p-limit": {
+          "version": "2.3.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "p-try": "^2.0.0"
+          }
+        },
+        "p-locate": {
+          "version": "4.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "p-limit": "^2.2.0"
+          }
+        },
+        "p-try": {
+          "version": "2.2.0",
+          "bundled": true,
+          "dev": true
+        },
+        "path-exists": {
+          "version": "4.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "path-is-absolute": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "pkg-dir": {
+          "version": "4.2.0",
           "bundled": true,
           "dev": true,
           "requires": {
-            "mimic-fn": "^2.1.0"
+            "find-up": "^4.0.0"
           }
         },
-        "path-parse": {
-          "version": "1.0.6",
-          "bundled": true,
-          "dev": true
-        },
         "prop-types": {
           "version": "15.7.2",
           "bundled": true,
@@ -17004,14 +16995,6 @@
             "esprima": "~4.0.0"
           }
         },
-        "resolve": {
-          "version": "1.17.0",
-          "bundled": true,
-          "dev": true,
-          "requires": {
-            "path-parse": "^1.0.6"
-          }
-        },
         "resolve-from": {
           "version": "3.0.0",
           "bundled": true,
@@ -17027,14 +17010,18 @@
           }
         },
         "rimraf": {
-          "version": "2.7.1",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-          "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+          "version": "3.0.2",
+          "bundled": true,
           "dev": true,
           "requires": {
             "glob": "^7.1.3"
           }
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "bundled": true,
+          "dev": true
+        },
         "scheduler": {
           "version": "0.18.0",
           "bundled": true,
@@ -17045,7 +17032,7 @@
           }
         },
         "semver": {
-          "version": "5.7.1",
+          "version": "6.3.0",
           "bundled": true,
           "dev": true
         },
@@ -17065,11 +17052,10 @@
           },
           "dependencies": {
             "ansi-styles": {
-              "version": "4.2.1",
+              "version": "4.3.0",
               "bundled": true,
               "dev": true,
               "requires": {
-                "@types/color-name": "^1.1.1",
                 "color-convert": "^2.0.1"
               }
             },
@@ -17088,6 +17074,11 @@
             }
           }
         },
+        "source-map": {
+          "version": "0.5.7",
+          "bundled": true,
+          "dev": true
+        },
         "string-length": {
           "version": "3.1.0",
           "bundled": true,
@@ -17118,21 +17109,28 @@
           }
         },
         "string-width": {
-          "version": "4.2.0",
+          "version": "4.2.2",
           "bundled": true,
           "dev": true,
           "requires": {
             "emoji-regex": "^8.0.0",
             "is-fullwidth-code-point": "^3.0.0",
             "strip-ansi": "^6.0.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "6.0.0",
-          "bundled": true,
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^5.0.0"
+          },
+          "dependencies": {
+            "ansi-regex": {
+              "version": "5.0.0",
+              "bundled": true,
+              "dev": true
+            },
+            "strip-ansi": {
+              "version": "6.0.0",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "ansi-regex": "^5.0.0"
+              }
+            }
           }
         },
         "supports-color": {
@@ -17144,7 +17142,7 @@
           }
         },
         "tap-parser": {
-          "version": "10.0.1",
+          "version": "10.1.0",
           "bundled": true,
           "dev": true,
           "requires": {
@@ -17167,13 +17165,13 @@
           "dev": true
         },
         "treport": {
-          "version": "1.0.2",
+          "version": "2.0.0",
           "bundled": true,
           "dev": true,
           "requires": {
             "cardinal": "^2.1.1",
             "chalk": "^3.0.0",
-            "import-jsx": "^3.1.0",
+            "import-jsx": "^4.0.0",
             "ink": "^2.6.0",
             "ms": "^2.1.2",
             "string-length": "^3.1.0",
@@ -17182,11 +17180,10 @@
           },
           "dependencies": {
             "ansi-styles": {
-              "version": "4.2.1",
+              "version": "4.3.0",
               "bundled": true,
               "dev": true,
               "requires": {
-                "@types/color-name": "^1.1.1",
                 "color-convert": "^2.0.1"
               }
             },
@@ -17218,7 +17215,7 @@
               "dev": true
             },
             "supports-color": {
-              "version": "7.1.0",
+              "version": "7.2.0",
               "bundled": true,
               "dev": true,
               "requires": {
@@ -17228,7 +17225,7 @@
           }
         },
         "type-fest": {
-          "version": "0.11.0",
+          "version": "0.21.3",
           "bundled": true,
           "dev": true
         },
@@ -17274,12 +17271,16 @@
             "strip-ansi": "^6.0.0"
           },
           "dependencies": {
+            "ansi-regex": {
+              "version": "5.0.0",
+              "bundled": true,
+              "dev": true
+            },
             "ansi-styles": {
-              "version": "4.2.1",
+              "version": "4.3.0",
               "bundled": true,
               "dev": true,
               "requires": {
-                "@types/color-name": "^1.1.1",
                 "color-convert": "^2.0.1"
               }
             },
@@ -17295,16 +17296,34 @@
               "version": "1.1.4",
               "bundled": true,
               "dev": true
+            },
+            "strip-ansi": {
+              "version": "6.0.0",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "ansi-regex": "^5.0.0"
+              }
             }
           }
         },
+        "wrappy": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true
+        },
+        "yallist": {
+          "version": "4.0.0",
+          "bundled": true,
+          "dev": true
+        },
         "yaml": {
-          "version": "1.10.0",
+          "version": "1.10.2",
           "bundled": true,
           "dev": true
         },
         "yoga-layout-prebuilt": {
-          "version": "1.9.6",
+          "version": "1.10.0",
           "bundled": true,
           "dev": true,
           "requires": {
@@ -17417,151 +17436,31 @@
       }
     },
     "tcompare": {
-      "version": "3.0.5",
-      "resolved": "https://registry.npmjs.org/tcompare/-/tcompare-3.0.5.tgz",
-      "integrity": "sha512-+tmloQj1buaShBX+LP1i1NF5riJm110Yr0flIJAEoKf01tFVoMZvW2jq1JLqaW8fspOUVPm5NKKW5qLwT0ETDQ==",
+      "version": "5.0.4",
+      "resolved": "https://registry.npmjs.org/tcompare/-/tcompare-5.0.4.tgz",
+      "integrity": "sha512-worXBcrmLoFu9oJYAKznjPE89APTEXk/XCazuDuSQfK1EqX3bpLPW3cY/RQucbcc7mW+yKW0duujsuFlU7dRCA==",
       "dev": true,
       "requires": {
-        "diff-frag": "^1.0.1"
+        "diff": "^4.0.2"
+      },
+      "dependencies": {
+        "diff": {
+          "version": "4.0.2",
+          "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+          "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+          "dev": true
+        }
       }
     },
     "test-exclude": {
-      "version": "5.2.3",
-      "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz",
-      "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==",
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+      "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
       "dev": true,
       "requires": {
-        "glob": "^7.1.3",
-        "minimatch": "^3.0.4",
-        "read-pkg-up": "^4.0.0",
-        "require-main-filename": "^2.0.0"
-      },
-      "dependencies": {
-        "find-up": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
-          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
-          "dev": true,
-          "requires": {
-            "locate-path": "^3.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==",
-          "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": {
-            "graceful-fs": "^4.1.2",
-            "parse-json": "^4.0.0",
-            "pify": "^3.0.0",
-            "strip-bom": "^3.0.0"
-          }
-        },
-        "locate-path": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
-          "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
-          "dev": true,
-          "requires": {
-            "p-locate": "^3.0.0",
-            "path-exists": "^3.0.0"
-          }
-        },
-        "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": {
-            "hosted-git-info": "^2.1.4",
-            "resolve": "^1.10.0",
-            "semver": "2 || 3 || 4 || 5",
-            "validate-npm-package-license": "^3.0.1"
-          }
-        },
-        "p-limit": {
-          "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
-          "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
-          "dev": true,
-          "requires": {
-            "p-try": "^2.0.0"
-          }
-        },
-        "p-locate": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
-          "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
-          "dev": true,
-          "requires": {
-            "p-limit": "^2.0.0"
-          }
-        },
-        "p-try": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
-          "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
-          "dev": true
-        },
-        "parse-json": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
-          "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
-          "dev": true,
-          "requires": {
-            "error-ex": "^1.3.1",
-            "json-parse-better-errors": "^1.0.1"
-          }
-        },
-        "path-type": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
-          "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
-          "dev": true,
-          "requires": {
-            "pify": "^3.0.0"
-          }
-        },
-        "pify": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
-          "dev": true
-        },
-        "read-pkg": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
-          "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
-          "dev": true,
-          "requires": {
-            "load-json-file": "^4.0.0",
-            "normalize-package-data": "^2.3.2",
-            "path-type": "^3.0.0"
-          }
-        },
-        "read-pkg-up": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz",
-          "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==",
-          "dev": true,
-          "requires": {
-            "find-up": "^3.0.0",
-            "read-pkg": "^3.0.0"
-          }
-        },
-        "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-          "dev": true
-        }
+        "@istanbuljs/schema": "^0.1.2",
+        "glob": "^7.1.4",
+        "minimatch": "^3.0.4"
       }
     },
     "text-table": {
@@ -17638,27 +17537,6 @@
       "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==",
       "dev": true
     },
-    "ts-node": {
-      "version": "8.10.2",
-      "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz",
-      "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==",
-      "dev": true,
-      "requires": {
-        "arg": "^4.1.0",
-        "diff": "^4.0.1",
-        "make-error": "^1.1.1",
-        "source-map-support": "^0.5.17",
-        "yn": "3.1.1"
-      },
-      "dependencies": {
-        "diff": {
-          "version": "4.0.2",
-          "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
-          "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
-          "dev": true
-        }
-      }
-    },
     "tsconfig-paths": {
       "version": "3.9.0",
       "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz",
@@ -17718,22 +17596,16 @@
         "is-typedarray": "^1.0.0"
       }
     },
-    "typescript": {
-      "version": "3.9.9",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz",
-      "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==",
-      "dev": 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"
       }
     },
     "unherit": {
@@ -17811,9 +17683,9 @@
       "dev": true
     },
     "unist-util-remove": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.0.1.tgz",
-      "integrity": "sha512-YtuetK6o16CMfG+0u4nndsWpujgsHDHHLyE0yGpJLLn5xSjKeyGyzEBOI2XbmoUHCYabmNgX52uxlWoQhcvR7Q==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz",
+      "integrity": "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==",
       "dev": true,
       "requires": {
         "unist-util-is": "^4.0.0"
@@ -17952,12 +17824,6 @@
         "unist-util-stringify-position": "^2.0.0"
       }
     },
-    "vlq": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
-      "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==",
-      "dev": true
-    },
     "w3c-hr-time": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
@@ -18065,12 +17931,6 @@
       "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
       "dev": true
     },
-    "which-pm-runs": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
-      "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
-      "dev": true
-    },
     "wide-align": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
@@ -18159,9 +18019,9 @@
       "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": {
@@ -18182,87 +18042,64 @@
       "dev": true
     },
     "yargs": {
-      "version": "13.3.2",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
-      "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+      "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": {
-        "cliui": "^5.0.0",
-        "find-up": "^3.0.0",
+        "cliui": "^6.0.0",
+        "decamelize": "^1.2.0",
+        "find-up": "^4.1.0",
         "get-caller-file": "^2.0.1",
         "require-directory": "^2.1.1",
         "require-main-filename": "^2.0.0",
         "set-blocking": "^2.0.0",
-        "string-width": "^3.0.0",
+        "string-width": "^4.2.0",
         "which-module": "^2.0.0",
         "y18n": "^4.0.0",
-        "yargs-parser": "^13.1.2"
+        "yargs-parser": "^18.1.2"
       },
       "dependencies": {
         "ansi-regex": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
           "dev": true
         },
-        "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==",
-          "dev": true,
-          "requires": {
-            "color-convert": "^1.9.0"
-          }
-        },
         "cliui": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
-          "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+          "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
           "dev": true,
           "requires": {
-            "string-width": "^3.1.0",
-            "strip-ansi": "^5.2.0",
-            "wrap-ansi": "^5.1.0"
+            "string-width": "^4.2.0",
+            "strip-ansi": "^6.0.0",
+            "wrap-ansi": "^6.2.0"
           }
         },
-        "color-convert": {
-          "version": "1.9.3",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-          "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+        "find-up": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+          "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
           "dev": true,
           "requires": {
-            "color-name": "1.1.3"
+            "locate-path": "^5.0.0",
+            "path-exists": "^4.0.0"
           }
         },
-        "color-name": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-          "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
-          "dev": true
-        },
-        "emoji-regex": {
-          "version": "7.0.3",
-          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
-          "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
-          "dev": true
-        },
-        "find-up": {
+        "is-fullwidth-code-point": {
           "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
-          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
-          "dev": true,
-          "requires": {
-            "locate-path": "^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
         },
         "locate-path": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
-          "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+          "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
           "dev": true,
           "requires": {
-            "p-locate": "^3.0.0",
-            "path-exists": "^3.0.0"
+            "p-locate": "^4.1.0"
           }
         },
         "p-limit": {
@@ -18275,12 +18112,12 @@
           }
         },
         "p-locate": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
-          "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+          "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
           "dev": true,
           "requires": {
-            "p-limit": "^2.0.0"
+            "p-limit": "^2.2.0"
           }
         },
         "p-try": {
@@ -18289,55 +18126,55 @@
           "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
           "dev": true
         },
+        "path-exists": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+          "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+          "dev": true
+        },
         "string-width": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+          "version": "4.2.2",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
+          "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
           "dev": true,
           "requires": {
-            "emoji-regex": "^7.0.1",
-            "is-fullwidth-code-point": "^2.0.0",
-            "strip-ansi": "^5.1.0"
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^6.0.0"
           }
         },
         "strip-ansi": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
           "dev": true,
           "requires": {
-            "ansi-regex": "^4.1.0"
+            "ansi-regex": "^5.0.0"
           }
         },
         "wrap-ansi": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
-          "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+          "version": "6.2.0",
+          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+          "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
           "dev": true,
           "requires": {
-            "ansi-styles": "^3.2.0",
-            "string-width": "^3.0.0",
-            "strip-ansi": "^5.0.0"
+            "ansi-styles": "^4.0.0",
+            "string-width": "^4.1.0",
+            "strip-ansi": "^6.0.0"
           }
         }
       }
     },
     "yargs-parser": {
-      "version": "13.1.2",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
-      "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+      "version": "18.1.3",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+      "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
       "dev": true,
       "requires": {
         "camelcase": "^5.0.0",
         "decamelize": "^1.2.0"
       }
     },
-    "yn": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
-      "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
-      "dev": true
-    },
     "zwitch": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz",
diff --git a/package.json b/package.json
index 65f9b8e7adf43..c21340888f7df 100644
--- a/package.json
+++ b/package.json
@@ -188,8 +188,7 @@
     "jsdom": "^16.5.2",
     "licensee": "^8.1.0",
     "marked-man": "^0.7.0",
-    "require-inject": "^1.4.4",
-    "tap": "^14.11.0",
+    "tap": "^15.0.2",
     "yaml": "^1.10.2"
   },
   "scripts": {
@@ -219,7 +218,6 @@
     "files": "test/{lib,bin}",
     "coverage-map": "test/coverage-map.js",
     "check-coverage": true,
-    "esm": false,
     "timeout": 600
   },
   "license": "Artistic-2.0",
diff --git a/smoke-tests/index.js b/smoke-tests/index.js
index 1d352c62550db..d16f498725d73 100644
--- a/smoke-tests/index.js
+++ b/smoke-tests/index.js
@@ -16,9 +16,9 @@ t.cleanSnapshot = s => s.split(cwd).join('{CWD}')
   .replace(/^npm@.*\ /mg, 'npm ')
 
 // setup server
-const registryServer = require('./server.js')
-const { registry } = registryServer
-t.test('setup server', { bail: true, buffered: false }, registryServer)
+const { start, stop, registry } = require('./server.js')
+t.before(start)
+t.teardown(stop)
 
 // setup fixtures
 const path = t.testdir({
diff --git a/smoke-tests/server.js b/smoke-tests/server.js
index 88cb5883da746..03aacb4b8c28a 100644
--- a/smoke-tests/server.js
+++ b/smoke-tests/server.js
@@ -14,8 +14,8 @@ let advisoryBulkResponse = null
 let failAdvisoryBulk = false
 let auditResponse = null
 let failAudit = false
-const startServer = cb => {
-  const server = module.exports.server = http.createServer((req, res) => {
+const startServer = () => new Promise((res, rej) => {
+  const server = exports.server = http.createServer((req, res) => {
     res.setHeader('connection', 'close')
 
     if (req.url === '/-/npm/v1/security/advisories/bulk') {
@@ -226,15 +226,10 @@ const startServer = cb => {
       res.end(er.stack)
     }
   })
-  server.listen(PORT, cb)
-}
-
-module.exports = t => startServer(() => {
-  t.parent.teardown(() => module.exports.server.close())
-  t.end()
+  server.listen(PORT, res)
 })
 
-module.exports.auditResponse = value => {
+exports.auditResponse = value => {
   if (auditResponse && auditResponse !== value) {
     throw new Error('setting audit response, but already set\n' +
       '(did you forget to call the returned function on teardown?)')
@@ -242,12 +237,12 @@ module.exports.auditResponse = value => {
   auditResponse = value
   return () => auditResponse = null
 }
-module.exports.failAudit = () => {
+exports.failAudit = () => {
   failAudit = true
   return () => failAudit = false
 }
 
-module.exports.advisoryBulkResponse = value => {
+exports.advisoryBulkResponse = value => {
   if (advisoryBulkResponse && advisoryBulkResponse !== value) {
     throw new Error('setting advisory bulk response, but already set\n' +
       '(did you forget to call the returned function on teardown?)')
@@ -255,22 +250,22 @@ module.exports.advisoryBulkResponse = value => {
   advisoryBulkResponse = value
   return () => advisoryBulkResponse = null
 }
-module.exports.failAdvisoryBulk = () => {
+exports.failAdvisoryBulk = () => {
   failAdvisoryBulk = true
   return () => failAdvisoryBulk = false
 }
 
-module.exports.registry = `http://localhost:${PORT}/`
+exports.registry = `http://localhost:${PORT}/`
 
-module.exports.start = startServer
-module.exports.stop = () => module.exports.server.close()
+exports.start = startServer
+exports.stop = () => exports.server.close()
 
 if (require.main === module) {
-  startServer(() => {
+  startServer().then(() => {
     console.log(`Mock registry live at:
-  ${module.exports.registry}
+  ${exports.registry}
 Press ^D to close gracefully.`)
   })
   process.openStdin()
-  process.stdin.on('end', () => module.exports.server.close())
+  process.stdin.on('end', () => exports.stop())
 }
diff --git a/tap-snapshots/smoke-tests-index.js-TAP.test.js b/tap-snapshots/smoke-tests/index.js.test.cjs
similarity index 98%
rename from tap-snapshots/smoke-tests-index.js-TAP.test.js
rename to tap-snapshots/smoke-tests/index.js.test.cjs
index 6fabc5cc30038..89c0cb20b5e36 100644
--- a/tap-snapshots/smoke-tests-index.js-TAP.test.js
+++ b/tap-snapshots/smoke-tests/index.js.test.cjs
@@ -32,7 +32,7 @@ All commands:
     unstar, update, version, view, whoami
 
 Specify configs in the ini-formatted file:
-    {CWD}/smoke-tests/index/.npmrc
+    {CWD}/smoke-tests/tap-testdir-index/.npmrc
 or on the command line via: npm  --key=value
 
 More configuration info: npm help config
@@ -313,7 +313,7 @@ project@1.0.0
 `
 
 exports[`smoke-tests/index.js TAP npm init > should have successful npm init result 1`] = `
-Wrote to {CWD}/smoke-tests/index/project/package.json:
+Wrote to {CWD}/smoke-tests/tap-testdir-index/project/package.json:
 
 {
   "name": "project",
@@ -469,7 +469,7 @@ exports[`smoke-tests/index.js TAP npm install prodDep@version > should have expe
 `
 
 exports[`smoke-tests/index.js TAP npm ls > should have expected ls output 1`] = `
-project@1.0.0 {CWD}/smoke-tests/index/project
+project@1.0.0 {CWD}/smoke-tests/tap-testdir-index/project
 +-- abbrev@1.0.4
 \`-- promise-all-reject-late@1.0.1
 
@@ -483,7 +483,7 @@ abbrev     1.0.4   1.1.1   1.1.1  node_modules/abbrev  project
 `
 
 exports[`smoke-tests/index.js TAP npm prefix > should have expected prefix output 1`] = `
-{CWD}/smoke-tests/index/project
+{CWD}/smoke-tests/tap-testdir-index/project
 
 `
 
diff --git a/tap-snapshots/test-lib-link.js-TAP.test.js b/tap-snapshots/test-lib-link.js-TAP.test.js
deleted file mode 100644
index ab1d5c6b830fb..0000000000000
--- a/tap-snapshots/test-lib-link.js-TAP.test.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/* IMPORTANT
- * This snapshot file is auto-generated, but designed for humans.
- * It should be checked into source control and tracked carefully.
- * Re-generate by setting TAP_SNAPSHOT=1 and running tests.
- * Make sure to inspect the output below.  Do not ignore changes!
- */
-'use strict'
-exports[`test/lib/link.js TAP link global linked pkg to local nm when using args > should create a local symlink to global pkg 1`] = `
-{CWD}/test/lib/link-link-global-linked-pkg-to-local-nm-when-using-args/my-project/node_modules/@myscope/bar -> {CWD}/test/lib/link-link-global-linked-pkg-to-local-nm-when-using-args/global-prefix/lib/node_modules/@myscope/bar
-{CWD}/test/lib/link-link-global-linked-pkg-to-local-nm-when-using-args/my-project/node_modules/@myscope/linked -> {CWD}/test/lib/link-link-global-linked-pkg-to-local-nm-when-using-args/scoped-linked
-{CWD}/test/lib/link-link-global-linked-pkg-to-local-nm-when-using-args/my-project/node_modules/a -> {CWD}/test/lib/link-link-global-linked-pkg-to-local-nm-when-using-args/global-prefix/lib/node_modules/a
-{CWD}/test/lib/link-link-global-linked-pkg-to-local-nm-when-using-args/my-project/node_modules/link-me-too -> {CWD}/test/lib/link-link-global-linked-pkg-to-local-nm-when-using-args/link-me-too
-{CWD}/test/lib/link-link-global-linked-pkg-to-local-nm-when-using-args/my-project/node_modules/test-pkg-link -> {CWD}/test/lib/link-link-global-linked-pkg-to-local-nm-when-using-args/test-pkg-link
-
-`
-
-exports[`test/lib/link.js TAP link pkg already in global space > should create a local symlink to global pkg 1`] = `
-{CWD}/test/lib/link-link-pkg-already-in-global-space/my-project/node_modules/@myscope/linked -> {CWD}/test/lib/link-link-pkg-already-in-global-space/scoped-linked
-
-`
-
-exports[`test/lib/link.js TAP link pkg already in global space when prefix is a symlink > should create a local symlink to global pkg 1`] = `
-{CWD}/test/lib/link-link-pkg-already-in-global-space-when-prefix-is-a-symlink/my-project/node_modules/@myscope/linked -> {CWD}/test/lib/link-link-pkg-already-in-global-space-when-prefix-is-a-symlink/scoped-linked
-
-`
-
-exports[`test/lib/link.js TAP link to globalDir when in current working dir of pkg and no args > should create a global link to current pkg 1`] = `
-{CWD}/test/lib/link-link-to-globalDir-when-in-current-working-dir-of-pkg-and-no-args/global-prefix/lib/node_modules/test-pkg-link -> {CWD}/test/lib/link-link-to-globalDir-when-in-current-working-dir-of-pkg-and-no-args/test-pkg-link
-
-`
diff --git a/tap-snapshots/test-lib-outdated.js-TAP.test.js b/tap-snapshots/test-lib-outdated.js-TAP.test.js
deleted file mode 100644
index 7f245b09ed920..0000000000000
--- a/tap-snapshots/test-lib-outdated.js-TAP.test.js
+++ /dev/null
@@ -1,154 +0,0 @@
-/* IMPORTANT
- * This snapshot file is auto-generated, but designed for humans.
- * It should be checked into source control and tracked carefully.
- * Re-generate by setting TAP_SNAPSHOT=1 and running tests.
- * Make sure to inspect the output below.  Do not ignore changes!
- */
-'use strict'
-exports[`test/lib/outdated.js TAP should display outdated deps outdated --all > must match snapshot 1`] = `
-
-Package  Current  Wanted  Latest  Location            Depended by
-alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  outdated-should-display-outdated-deps
-beta       1.0.0   1.0.1   1.0.1  node_modules/beta   outdated-should-display-outdated-deps
-gamma      1.0.1   1.0.1   2.0.0  node_modules/gamma  outdated-should-display-outdated-deps
-theta    MISSING   1.0.1   1.0.1  -                   outdated-should-display-outdated-deps
-`
-
-exports[`test/lib/outdated.js TAP should display outdated deps outdated --json --long > must match snapshot 1`] = `
-
-{
-  "alpha": {
-    "current": "1.0.0",
-    "wanted": "1.0.1",
-    "latest": "1.0.1",
-    "dependent": "outdated-should-display-outdated-deps",
-    "location": "{CWD}/test/lib/outdated-should-display-outdated-deps/node_modules/alpha",
-    "type": "dependencies"
-  },
-  "beta": {
-    "current": "1.0.0",
-    "wanted": "1.0.1",
-    "latest": "1.0.1",
-    "dependent": "outdated-should-display-outdated-deps",
-    "location": "{CWD}/test/lib/outdated-should-display-outdated-deps/node_modules/beta",
-    "type": "peerDependencies"
-  },
-  "gamma": {
-    "current": "1.0.1",
-    "wanted": "1.0.1",
-    "latest": "2.0.0",
-    "dependent": "outdated-should-display-outdated-deps",
-    "location": "{CWD}/test/lib/outdated-should-display-outdated-deps/node_modules/gamma",
-    "type": "dependencies"
-  },
-  "theta": {
-    "wanted": "1.0.1",
-    "latest": "1.0.1",
-    "dependent": "outdated-should-display-outdated-deps",
-    "type": "dependencies"
-  }
-}
-`
-
-exports[`test/lib/outdated.js TAP should display outdated deps outdated --json > must match snapshot 1`] = `
-
-{
-  "alpha": {
-    "current": "1.0.0",
-    "wanted": "1.0.1",
-    "latest": "1.0.1",
-    "dependent": "outdated-should-display-outdated-deps",
-    "location": "{CWD}/test/lib/outdated-should-display-outdated-deps/node_modules/alpha"
-  },
-  "beta": {
-    "current": "1.0.0",
-    "wanted": "1.0.1",
-    "latest": "1.0.1",
-    "dependent": "outdated-should-display-outdated-deps",
-    "location": "{CWD}/test/lib/outdated-should-display-outdated-deps/node_modules/beta"
-  },
-  "gamma": {
-    "current": "1.0.1",
-    "wanted": "1.0.1",
-    "latest": "2.0.0",
-    "dependent": "outdated-should-display-outdated-deps",
-    "location": "{CWD}/test/lib/outdated-should-display-outdated-deps/node_modules/gamma"
-  },
-  "theta": {
-    "wanted": "1.0.1",
-    "latest": "1.0.1",
-    "dependent": "outdated-should-display-outdated-deps"
-  }
-}
-`
-
-exports[`test/lib/outdated.js TAP should display outdated deps outdated --long > must match snapshot 1`] = `
-
-Package  Current  Wanted  Latest  Location            Depended by                            Package Type      Homepage
-alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  outdated-should-display-outdated-deps  dependencies
-beta       1.0.0   1.0.1   1.0.1  node_modules/beta   outdated-should-display-outdated-deps  peerDependencies
-gamma      1.0.1   1.0.1   2.0.0  node_modules/gamma  outdated-should-display-outdated-deps  dependencies
-theta    MISSING   1.0.1   1.0.1  -                   outdated-should-display-outdated-deps  dependencies
-`
-
-exports[`test/lib/outdated.js TAP should display outdated deps outdated --omit=dev --omit=peer > must match snapshot 1`] = `
-
-Package  Current  Wanted  Latest  Location            Depended by
-alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  outdated-should-display-outdated-deps
-gamma      1.0.1   1.0.1   2.0.0  node_modules/gamma  outdated-should-display-outdated-deps
-theta    MISSING   1.0.1   1.0.1  -                   outdated-should-display-outdated-deps
-`
-
-exports[`test/lib/outdated.js TAP should display outdated deps outdated --omit=dev > must match snapshot 1`] = `
-
-Package  Current  Wanted  Latest  Location            Depended by
-alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  outdated-should-display-outdated-deps
-beta       1.0.0   1.0.1   1.0.1  node_modules/beta   outdated-should-display-outdated-deps
-gamma      1.0.1   1.0.1   2.0.0  node_modules/gamma  outdated-should-display-outdated-deps
-theta    MISSING   1.0.1   1.0.1  -                   outdated-should-display-outdated-deps
-`
-
-exports[`test/lib/outdated.js TAP should display outdated deps outdated --omit=prod > must match snapshot 1`] = `
-
-Package  Current  Wanted  Latest  Location            Depended by
-alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  outdated-should-display-outdated-deps
-beta       1.0.0   1.0.1   1.0.1  node_modules/beta   outdated-should-display-outdated-deps
-gamma      1.0.1   1.0.1   2.0.0  node_modules/gamma  outdated-should-display-outdated-deps
-`
-
-exports[`test/lib/outdated.js TAP should display outdated deps outdated --parseable --long > must match snapshot 1`] = `
-
-{CWD}/test/lib/outdated-should-display-outdated-deps/node_modules/alpha:alpha@1.0.1:alpha@1.0.0:alpha@1.0.1:outdated-should-display-outdated-deps:dependencies:
-{CWD}/test/lib/outdated-should-display-outdated-deps/node_modules/beta:beta@1.0.1:beta@1.0.0:beta@1.0.1:outdated-should-display-outdated-deps:peerDependencies:
-{CWD}/test/lib/outdated-should-display-outdated-deps/node_modules/gamma:gamma@1.0.1:gamma@1.0.1:gamma@2.0.0:outdated-should-display-outdated-deps:dependencies:
-:theta@1.0.1:MISSING:theta@1.0.1:outdated-should-display-outdated-deps:dependencies:
-`
-
-exports[`test/lib/outdated.js TAP should display outdated deps outdated --parseable > must match snapshot 1`] = `
-
-{CWD}/test/lib/outdated-should-display-outdated-deps/node_modules/alpha:alpha@1.0.1:alpha@1.0.0:alpha@1.0.1:outdated-should-display-outdated-deps
-{CWD}/test/lib/outdated-should-display-outdated-deps/node_modules/beta:beta@1.0.1:beta@1.0.0:beta@1.0.1:outdated-should-display-outdated-deps
-{CWD}/test/lib/outdated-should-display-outdated-deps/node_modules/gamma:gamma@1.0.1:gamma@1.0.1:gamma@2.0.0:outdated-should-display-outdated-deps
-:theta@1.0.1:MISSING:theta@1.0.1:outdated-should-display-outdated-deps
-`
-
-exports[`test/lib/outdated.js TAP should display outdated deps outdated > must match snapshot 1`] = `
-
-Package  Current  Wanted  Latest  Location            Depended by
-alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  outdated-should-display-outdated-deps
-beta       1.0.0   1.0.1   1.0.1  node_modules/beta   outdated-should-display-outdated-deps
-gamma      1.0.1   1.0.1   2.0.0  node_modules/gamma  outdated-should-display-outdated-deps
-theta    MISSING   1.0.1   1.0.1  -                   outdated-should-display-outdated-deps
-`
-
-exports[`test/lib/outdated.js TAP should display outdated deps outdated global > must match snapshot 1`] = `
-
-Package  Current  Wanted  Latest  Location            Depended by
-alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  global
-`
-
-exports[`test/lib/outdated.js TAP should display outdated deps outdated specific dep > must match snapshot 1`] = `
-
-Package  Current  Wanted  Latest  Location            Depended by
-alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  outdated-should-display-outdated-deps
-`
diff --git a/tap-snapshots/test-tap-repo.js-TAP.test.js b/tap-snapshots/test-tap-repo.js-TAP.test.js
deleted file mode 100644
index 3fba79edb8d42..0000000000000
--- a/tap-snapshots/test-tap-repo.js-TAP.test.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/* IMPORTANT
- * This snapshot file is auto-generated, but designed for humans.
- * It should be checked into source control and tracked carefully.
- * Re-generate by setting TAP_SNAPSHOT=1 and running tests.
- * Make sure to inspect the output below.  Do not ignore changes!
- */
-'use strict'
-exports[`test/tap/repo.js TAP npm repo underscore --json > should print json result 1`] = `
-{
-  "title": "repository available at the following URL",
-  "url": "https://github.com/jashkenas/underscore"
-}
-
-`
-
-exports[`test/tap/repo.js TAP npm repo underscore --no-browser > should print alternative msg 1`] = `
-repository available at the following URL:
-
-https://github.com/jashkenas/underscore
-
-`
diff --git a/tap-snapshots/test-lib-config.js-TAP.test.js b/tap-snapshots/test/lib/config.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-config.js-TAP.test.js
rename to tap-snapshots/test/lib/config.js.test.cjs
diff --git a/tap-snapshots/test-lib-dist-tag.js-TAP.test.js b/tap-snapshots/test/lib/dist-tag.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-dist-tag.js-TAP.test.js
rename to tap-snapshots/test/lib/dist-tag.js.test.cjs
diff --git a/tap-snapshots/test-lib-fund.js-TAP.test.js b/tap-snapshots/test/lib/fund.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-fund.js-TAP.test.js
rename to tap-snapshots/test/lib/fund.js.test.cjs
diff --git a/tap-snapshots/test-lib-init.js-TAP.test.js b/tap-snapshots/test/lib/init.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-init.js-TAP.test.js
rename to tap-snapshots/test/lib/init.js.test.cjs
diff --git a/tap-snapshots/test/lib/link.js.test.cjs b/tap-snapshots/test/lib/link.js.test.cjs
new file mode 100644
index 0000000000000..d6dd376593b4d
--- /dev/null
+++ b/tap-snapshots/test/lib/link.js.test.cjs
@@ -0,0 +1,30 @@
+/* IMPORTANT
+ * This snapshot file is auto-generated, but designed for humans.
+ * It should be checked into source control and tracked carefully.
+ * Re-generate by setting TAP_SNAPSHOT=1 and running tests.
+ * Make sure to inspect the output below.  Do not ignore changes!
+ */
+'use strict'
+exports[`test/lib/link.js TAP link global linked pkg to local nm when using args > should create a local symlink to global pkg 1`] = `
+{CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-nm-when-using-args/my-project/node_modules/@myscope/bar -> {CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-nm-when-using-args/global-prefix/lib/node_modules/@myscope/bar
+{CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-nm-when-using-args/my-project/node_modules/@myscope/linked -> {CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-nm-when-using-args/scoped-linked
+{CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-nm-when-using-args/my-project/node_modules/a -> {CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-nm-when-using-args/global-prefix/lib/node_modules/a
+{CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-nm-when-using-args/my-project/node_modules/link-me-too -> {CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-nm-when-using-args/link-me-too
+{CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-nm-when-using-args/my-project/node_modules/test-pkg-link -> {CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-nm-when-using-args/test-pkg-link
+
+`
+
+exports[`test/lib/link.js TAP link pkg already in global space > should create a local symlink to global pkg 1`] = `
+{CWD}/test/lib/tap-testdir-link-link-pkg-already-in-global-space/my-project/node_modules/@myscope/linked -> {CWD}/test/lib/tap-testdir-link-link-pkg-already-in-global-space/scoped-linked
+
+`
+
+exports[`test/lib/link.js TAP link pkg already in global space when prefix is a symlink > should create a local symlink to global pkg 1`] = `
+{CWD}/test/lib/tap-testdir-link-link-pkg-already-in-global-space-when-prefix-is-a-symlink/my-project/node_modules/@myscope/linked -> {CWD}/test/lib/tap-testdir-link-link-pkg-already-in-global-space-when-prefix-is-a-symlink/scoped-linked
+
+`
+
+exports[`test/lib/link.js TAP link to globalDir when in current working dir of pkg and no args > should create a global link to current pkg 1`] = `
+{CWD}/test/lib/tap-testdir-link-link-to-globalDir-when-in-current-working-dir-of-pkg-and-no-args/global-prefix/lib/node_modules/test-pkg-link -> {CWD}/test/lib/tap-testdir-link-link-to-globalDir-when-in-current-working-dir-of-pkg-and-no-args/test-pkg-link
+
+`
diff --git a/tap-snapshots/test-lib-ls.js-TAP.test.js b/tap-snapshots/test/lib/ls.js.test.cjs
similarity index 51%
rename from tap-snapshots/test-lib-ls.js-TAP.test.js
rename to tap-snapshots/test/lib/ls.js.test.cjs
index 120a65baffae9..c210ce928b7b3 100644
--- a/tap-snapshots/test-lib-ls.js-TAP.test.js
+++ b/tap-snapshots/test/lib/ls.js.test.cjs
@@ -6,14 +6,14 @@
  */
 'use strict'
 exports[`test/lib/ls.js TAP ls --depth=0 > should output tree containing only top-level dependencies 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls--depth-0
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls---depth-0
 +-- foo@1.0.0
 \`-- lorem@1.0.0
 
 `
 
 exports[`test/lib/ls.js TAP ls --depth=1 > should output tree containing top-level deps and their deps only 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls--depth-1
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls---depth-1
 +-- a@1.0.0
 | \`-- b@1.0.0
 \`-- e@1.0.0
@@ -21,7 +21,7 @@ test-npm-ls@1.0.0 {CWD}/ls-ls--depth-1
 `
 
 exports[`test/lib/ls.js TAP ls --dev > should output tree containing dev deps 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls--dev
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls---dev
 \`-- dev-dep@1.0.0
   \`-- foo@1.0.0
     \`-- bar@1.0.0
@@ -29,14 +29,14 @@ test-npm-ls@1.0.0 {CWD}/ls-ls--dev
 `
 
 exports[`test/lib/ls.js TAP ls --link > should output tree containing linked deps 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls--link
-\`-- linked-dep@1.0.0 -> {CWD}/ls-ls--link/linked-dep
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls---link
+\`-- linked-dep@1.0.0 -> {CWD}/tap-testdir-ls-ls---link/linked-dep
 
 `
 
 exports[`test/lib/ls.js TAP ls --long --depth=0 > should output tree containing top-level deps with descriptions 1`] = `
 test-npm-ls@1.0.0
-| {CWD}/ls-ls--long-depth-0
+| {CWD}/tap-testdir-ls-ls---long---depth-0
 | 
 +-- dev-dep@1.0.0
 |   A DEV dep kind of dep
@@ -53,7 +53,7 @@ test-npm-ls@1.0.0
 
 exports[`test/lib/ls.js TAP ls --long > should output tree info with descriptions 1`] = `
 test-npm-ls@1.0.0
-| {CWD}/ls-ls--long
+| {CWD}/tap-testdir-ls-ls---long
 | 
 +-- dev-dep@1.0.0
 | | A DEV dep kind of dep
@@ -75,7 +75,7 @@ test-npm-ls@1.0.0
 `
 
 exports[`test/lib/ls.js TAP ls --only=development > should output tree containing only development deps 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls--only-development
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls---only-development
 \`-- dev-dep@1.0.0
   \`-- foo@1.0.0
     \`-- bar@1.0.0
@@ -83,7 +83,7 @@ test-npm-ls@1.0.0 {CWD}/ls-ls--only-development
 `
 
 exports[`test/lib/ls.js TAP ls --only=prod > should output tree containing only prod deps 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls--only-prod
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls---only-prod
 +-- lorem@1.0.0
 +-- optional-dep@1.0.0
 \`-- prod-dep@1.0.0
@@ -92,207 +92,207 @@ test-npm-ls@1.0.0 {CWD}/ls-ls--only-prod
 `
 
 exports[`test/lib/ls.js TAP ls --parseable --depth=0 > should output tree containing only top-level dependencies 1`] = `
-{CWD}/ls-ls-parseable--depth-0
-{CWD}/ls-ls-parseable--depth-0/node_modules/foo
-{CWD}/ls-ls-parseable--depth-0/node_modules/lorem
+{CWD}/tap-testdir-ls-ls---parseable---depth-0
+{CWD}/tap-testdir-ls-ls---parseable---depth-0/node_modules/foo
+{CWD}/tap-testdir-ls-ls---parseable---depth-0/node_modules/lorem
 `
 
 exports[`test/lib/ls.js TAP ls --parseable --depth=1 > should output parseable containing top-level deps and their deps only 1`] = `
-{CWD}/ls-ls-parseable--depth-1
-{CWD}/ls-ls-parseable--depth-1/node_modules/foo
-{CWD}/ls-ls-parseable--depth-1/node_modules/lorem
-{CWD}/ls-ls-parseable--depth-1/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable---depth-1
+{CWD}/tap-testdir-ls-ls---parseable---depth-1/node_modules/foo
+{CWD}/tap-testdir-ls-ls---parseable---depth-1/node_modules/lorem
+{CWD}/tap-testdir-ls-ls---parseable---depth-1/node_modules/bar
 `
 
 exports[`test/lib/ls.js TAP ls --parseable --dev > should output tree containing dev deps 1`] = `
-{CWD}/ls-ls-parseable--dev
-{CWD}/ls-ls-parseable--dev/node_modules/dev-dep
-{CWD}/ls-ls-parseable--dev/node_modules/foo
-{CWD}/ls-ls-parseable--dev/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable---dev
+{CWD}/tap-testdir-ls-ls---parseable---dev/node_modules/dev-dep
+{CWD}/tap-testdir-ls-ls---parseable---dev/node_modules/foo
+{CWD}/tap-testdir-ls-ls---parseable---dev/node_modules/bar
 `
 
 exports[`test/lib/ls.js TAP ls --parseable --link > should output tree containing linked deps 1`] = `
-{CWD}/ls-ls-parseable--link
-{CWD}/ls-ls-parseable--link/node_modules/linked-dep
+{CWD}/tap-testdir-ls-ls---parseable---link
+{CWD}/tap-testdir-ls-ls---parseable---link/node_modules/linked-dep
 `
 
 exports[`test/lib/ls.js TAP ls --parseable --long --depth=0 > should output tree containing top-level deps with descriptions 1`] = `
-{CWD}/ls-ls-parseable--long-depth-0:test-npm-ls@1.0.0
-{CWD}/ls-ls-parseable--long-depth-0/node_modules/dev-dep:dev-dep@1.0.0
-{CWD}/ls-ls-parseable--long-depth-0/node_modules/lorem:lorem@1.0.0
-{CWD}/ls-ls-parseable--long-depth-0/node_modules/optional-dep:optional-dep@1.0.0
-{CWD}/ls-ls-parseable--long-depth-0/node_modules/peer-dep:peer-dep@1.0.0
-{CWD}/ls-ls-parseable--long-depth-0/node_modules/prod-dep:prod-dep@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long---depth-0:test-npm-ls@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long---depth-0/node_modules/dev-dep:dev-dep@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long---depth-0/node_modules/lorem:lorem@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long---depth-0/node_modules/optional-dep:optional-dep@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long---depth-0/node_modules/peer-dep:peer-dep@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long---depth-0/node_modules/prod-dep:prod-dep@1.0.0
 `
 
 exports[`test/lib/ls.js TAP ls --parseable --long > should output tree info with descriptions 1`] = `
-{CWD}/ls-ls-parseable--long:test-npm-ls@1.0.0
-{CWD}/ls-ls-parseable--long/node_modules/dev-dep:dev-dep@1.0.0
-{CWD}/ls-ls-parseable--long/node_modules/lorem:lorem@1.0.0
-{CWD}/ls-ls-parseable--long/node_modules/optional-dep:optional-dep@1.0.0
-{CWD}/ls-ls-parseable--long/node_modules/peer-dep:peer-dep@1.0.0
-{CWD}/ls-ls-parseable--long/node_modules/prod-dep:prod-dep@1.0.0
-{CWD}/ls-ls-parseable--long/node_modules/foo:foo@1.0.0
-{CWD}/ls-ls-parseable--long/node_modules/prod-dep/node_modules/bar:bar@2.0.0
-{CWD}/ls-ls-parseable--long/node_modules/bar:bar@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long:test-npm-ls@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long/node_modules/dev-dep:dev-dep@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long/node_modules/lorem:lorem@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long/node_modules/optional-dep:optional-dep@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long/node_modules/peer-dep:peer-dep@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long/node_modules/prod-dep:prod-dep@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long/node_modules/foo:foo@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long/node_modules/prod-dep/node_modules/bar:bar@2.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long/node_modules/bar:bar@1.0.0
 `
 
 exports[`test/lib/ls.js TAP ls --parseable --long missing/invalid/extraneous > should output parseable result containing EXTRANEOUS/INVALID labels 1`] = `
-{CWD}/ls-ls-parseable--long-missing-invalid-extraneous:test-npm-ls@1.0.0
-{CWD}/ls-ls-parseable--long-missing-invalid-extraneous/node_modules/foo:foo@1.0.0:INVALID
-{CWD}/ls-ls-parseable--long-missing-invalid-extraneous/node_modules/lorem:lorem@1.0.0:EXTRANEOUS
-{CWD}/ls-ls-parseable--long-missing-invalid-extraneous/node_modules/bar:bar@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long-missing-invalid-extraneous:test-npm-ls@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long-missing-invalid-extraneous/node_modules/foo:foo@1.0.0:INVALID
+{CWD}/tap-testdir-ls-ls---parseable---long-missing-invalid-extraneous/node_modules/lorem:lorem@1.0.0:EXTRANEOUS
+{CWD}/tap-testdir-ls-ls---parseable---long-missing-invalid-extraneous/node_modules/bar:bar@1.0.0
 `
 
 exports[`test/lib/ls.js TAP ls --parseable --long print symlink target location > should output parseable results with symlink targets 1`] = `
-{CWD}/ls-ls-parseable--long-print-symlink-target-location:test-npm-ls@1.0.0
-{CWD}/ls-ls-parseable--long-print-symlink-target-location/node_modules/dev-dep:dev-dep@1.0.0
-{CWD}/ls-ls-parseable--long-print-symlink-target-location/node_modules/linked-dep:linked-dep@1.0.0:{CWD}/ls-ls-parseable--long-print-symlink-target-location/linked-dep
-{CWD}/ls-ls-parseable--long-print-symlink-target-location/node_modules/lorem:lorem@1.0.0
-{CWD}/ls-ls-parseable--long-print-symlink-target-location/node_modules/optional-dep:optional-dep@1.0.0
-{CWD}/ls-ls-parseable--long-print-symlink-target-location/node_modules/peer-dep:peer-dep@1.0.0
-{CWD}/ls-ls-parseable--long-print-symlink-target-location/node_modules/prod-dep:prod-dep@1.0.0
-{CWD}/ls-ls-parseable--long-print-symlink-target-location/node_modules/foo:foo@1.0.0
-{CWD}/ls-ls-parseable--long-print-symlink-target-location/node_modules/prod-dep/node_modules/bar:bar@2.0.0
-{CWD}/ls-ls-parseable--long-print-symlink-target-location/node_modules/bar:bar@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long-print-symlink-target-location:test-npm-ls@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long-print-symlink-target-location/node_modules/dev-dep:dev-dep@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long-print-symlink-target-location/node_modules/linked-dep:linked-dep@1.0.0:{CWD}/tap-testdir-ls-ls---parseable---long-print-symlink-target-location/linked-dep
+{CWD}/tap-testdir-ls-ls---parseable---long-print-symlink-target-location/node_modules/lorem:lorem@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long-print-symlink-target-location/node_modules/optional-dep:optional-dep@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long-print-symlink-target-location/node_modules/peer-dep:peer-dep@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long-print-symlink-target-location/node_modules/prod-dep:prod-dep@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long-print-symlink-target-location/node_modules/foo:foo@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long-print-symlink-target-location/node_modules/prod-dep/node_modules/bar:bar@2.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long-print-symlink-target-location/node_modules/bar:bar@1.0.0
 `
 
 exports[`test/lib/ls.js TAP ls --parseable --long with extraneous deps > should output long parseable output with extraneous info 1`] = `
-{CWD}/ls-ls-parseable--long-with-extraneous-deps:test-npm-ls@1.0.0
-{CWD}/ls-ls-parseable--long-with-extraneous-deps/node_modules/foo:foo@1.0.0
-{CWD}/ls-ls-parseable--long-with-extraneous-deps/node_modules/lorem:lorem@1.0.0:EXTRANEOUS
-{CWD}/ls-ls-parseable--long-with-extraneous-deps/node_modules/bar:bar@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long-with-extraneous-deps:test-npm-ls@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long-with-extraneous-deps/node_modules/foo:foo@1.0.0
+{CWD}/tap-testdir-ls-ls---parseable---long-with-extraneous-deps/node_modules/lorem:lorem@1.0.0:EXTRANEOUS
+{CWD}/tap-testdir-ls-ls---parseable---long-with-extraneous-deps/node_modules/bar:bar@1.0.0
 `
 
 exports[`test/lib/ls.js TAP ls --parseable --only=development > should output tree containing only development deps 1`] = `
-{CWD}/ls-ls-parseable--only-development
-{CWD}/ls-ls-parseable--only-development/node_modules/dev-dep
-{CWD}/ls-ls-parseable--only-development/node_modules/foo
-{CWD}/ls-ls-parseable--only-development/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable---only-development
+{CWD}/tap-testdir-ls-ls---parseable---only-development/node_modules/dev-dep
+{CWD}/tap-testdir-ls-ls---parseable---only-development/node_modules/foo
+{CWD}/tap-testdir-ls-ls---parseable---only-development/node_modules/bar
 `
 
 exports[`test/lib/ls.js TAP ls --parseable --only=prod > should output tree containing only prod deps 1`] = `
-{CWD}/ls-ls-parseable--only-prod
-{CWD}/ls-ls-parseable--only-prod/node_modules/lorem
-{CWD}/ls-ls-parseable--only-prod/node_modules/optional-dep
-{CWD}/ls-ls-parseable--only-prod/node_modules/prod-dep
-{CWD}/ls-ls-parseable--only-prod/node_modules/prod-dep/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable---only-prod
+{CWD}/tap-testdir-ls-ls---parseable---only-prod/node_modules/lorem
+{CWD}/tap-testdir-ls-ls---parseable---only-prod/node_modules/optional-dep
+{CWD}/tap-testdir-ls-ls---parseable---only-prod/node_modules/prod-dep
+{CWD}/tap-testdir-ls-ls---parseable---only-prod/node_modules/prod-dep/node_modules/bar
 `
 
 exports[`test/lib/ls.js TAP ls --parseable --production > should output tree containing production deps 1`] = `
-{CWD}/ls-ls-parseable--production
-{CWD}/ls-ls-parseable--production/node_modules/lorem
-{CWD}/ls-ls-parseable--production/node_modules/optional-dep
-{CWD}/ls-ls-parseable--production/node_modules/prod-dep
-{CWD}/ls-ls-parseable--production/node_modules/prod-dep/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable---production
+{CWD}/tap-testdir-ls-ls---parseable---production/node_modules/lorem
+{CWD}/tap-testdir-ls-ls---parseable---production/node_modules/optional-dep
+{CWD}/tap-testdir-ls-ls---parseable---production/node_modules/prod-dep
+{CWD}/tap-testdir-ls-ls---parseable---production/node_modules/prod-dep/node_modules/bar
 `
 
 exports[`test/lib/ls.js TAP ls --parseable cycle deps > should print tree output omitting deduped ref 1`] = `
-{CWD}/ls-ls-parseable-cycle-deps
-{CWD}/ls-ls-parseable-cycle-deps/node_modules/a
-{CWD}/ls-ls-parseable-cycle-deps/node_modules/b
+{CWD}/tap-testdir-ls-ls---parseable-cycle-deps
+{CWD}/tap-testdir-ls-ls---parseable-cycle-deps/node_modules/a
+{CWD}/tap-testdir-ls-ls---parseable-cycle-deps/node_modules/b
 `
 
 exports[`test/lib/ls.js TAP ls --parseable default --depth value should be 0 > should output parseable output containing only top-level dependencies 1`] = `
-{CWD}/ls-ls-parseable-default-depth-value-should-be-0
-{CWD}/ls-ls-parseable-default-depth-value-should-be-0/node_modules/foo
-{CWD}/ls-ls-parseable-default-depth-value-should-be-0/node_modules/lorem
+{CWD}/tap-testdir-ls-ls---parseable-default---depth-value-should-be-0
+{CWD}/tap-testdir-ls-ls---parseable-default---depth-value-should-be-0/node_modules/foo
+{CWD}/tap-testdir-ls-ls---parseable-default---depth-value-should-be-0/node_modules/lorem
 `
 
 exports[`test/lib/ls.js TAP ls --parseable empty location > should print empty result 1`] = `
-{CWD}/ls-ls-parseable-empty-location
+{CWD}/tap-testdir-ls-ls---parseable-empty-location
 `
 
 exports[`test/lib/ls.js TAP ls --parseable extraneous deps > should output containing problems info 1`] = `
-{CWD}/ls-ls-parseable-extraneous-deps
-{CWD}/ls-ls-parseable-extraneous-deps/node_modules/foo
-{CWD}/ls-ls-parseable-extraneous-deps/node_modules/lorem
-{CWD}/ls-ls-parseable-extraneous-deps/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable-extraneous-deps
+{CWD}/tap-testdir-ls-ls---parseable-extraneous-deps/node_modules/foo
+{CWD}/tap-testdir-ls-ls---parseable-extraneous-deps/node_modules/lorem
+{CWD}/tap-testdir-ls-ls---parseable-extraneous-deps/node_modules/bar
 `
 
 exports[`test/lib/ls.js TAP ls --parseable from and resolved properties > should not be printed in tree output 1`] = `
-{CWD}/ls-ls-parseable-from-and-resolved-properties
-{CWD}/ls-ls-parseable-from-and-resolved-properties/node_modules/simple-output
+{CWD}/tap-testdir-ls-ls---parseable-from-and-resolved-properties
+{CWD}/tap-testdir-ls-ls---parseable-from-and-resolved-properties/node_modules/simple-output
 `
 
 exports[`test/lib/ls.js TAP ls --parseable global > should print parseable output for global deps 1`] = `
-{CWD}/ls-ls-parseable-global
-{CWD}/ls-ls-parseable-global/node_modules/a
-{CWD}/ls-ls-parseable-global/node_modules/b
-{CWD}/ls-ls-parseable-global/node_modules/b/node_modules/c
+{CWD}/tap-testdir-ls-ls---parseable-global
+{CWD}/tap-testdir-ls-ls---parseable-global/node_modules/a
+{CWD}/tap-testdir-ls-ls---parseable-global/node_modules/b
+{CWD}/tap-testdir-ls-ls---parseable-global/node_modules/b/node_modules/c
 `
 
 exports[`test/lib/ls.js TAP ls --parseable json read problems > should print empty result 1`] = `
-{CWD}/ls-ls-parseable-json-read-problems
+{CWD}/tap-testdir-ls-ls---parseable-json-read-problems
 `
 
 exports[`test/lib/ls.js TAP ls --parseable missing package.json > should log all extraneous deps on error msg 1`] = `
-extraneous: bar@1.0.0 {CWD}/ls-ls-parseable-missing-package-json/node_modules/bar
-extraneous: foo@1.0.0 {CWD}/ls-ls-parseable-missing-package-json/node_modules/foo
-extraneous: lorem@1.0.0 {CWD}/ls-ls-parseable-missing-package-json/node_modules/lorem
+extraneous: bar@1.0.0 {CWD}/tap-testdir-ls-ls---parseable-missing-package.json/node_modules/bar
+extraneous: foo@1.0.0 {CWD}/tap-testdir-ls-ls---parseable-missing-package.json/node_modules/foo
+extraneous: lorem@1.0.0 {CWD}/tap-testdir-ls-ls---parseable-missing-package.json/node_modules/lorem
 `
 
 exports[`test/lib/ls.js TAP ls --parseable missing package.json > should output parseable missing name/version of top-level package 1`] = `
-{CWD}/ls-ls-parseable-missing-package-json
-{CWD}/ls-ls-parseable-missing-package-json/node_modules/bar
-{CWD}/ls-ls-parseable-missing-package-json/node_modules/foo
-{CWD}/ls-ls-parseable-missing-package-json/node_modules/lorem
+{CWD}/tap-testdir-ls-ls---parseable-missing-package.json
+{CWD}/tap-testdir-ls-ls---parseable-missing-package.json/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable-missing-package.json/node_modules/foo
+{CWD}/tap-testdir-ls-ls---parseable-missing-package.json/node_modules/lorem
 `
 
 exports[`test/lib/ls.js TAP ls --parseable missing/invalid/extraneous > should output parseable containing top-level deps and their deps only 1`] = `
-{CWD}/ls-ls-parseable-missing-invalid-extraneous
-{CWD}/ls-ls-parseable-missing-invalid-extraneous/node_modules/foo
-{CWD}/ls-ls-parseable-missing-invalid-extraneous/node_modules/lorem
-{CWD}/ls-ls-parseable-missing-invalid-extraneous/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable-missing-invalid-extraneous
+{CWD}/tap-testdir-ls-ls---parseable-missing-invalid-extraneous/node_modules/foo
+{CWD}/tap-testdir-ls-ls---parseable-missing-invalid-extraneous/node_modules/lorem
+{CWD}/tap-testdir-ls-ls---parseable-missing-invalid-extraneous/node_modules/bar
 `
 
 exports[`test/lib/ls.js TAP ls --parseable no args > should output parseable representation of dependencies structure 1`] = `
-{CWD}/ls-ls-parseable-no-args
-{CWD}/ls-ls-parseable-no-args/node_modules/foo
-{CWD}/ls-ls-parseable-no-args/node_modules/lorem
-{CWD}/ls-ls-parseable-no-args/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable-no-args
+{CWD}/tap-testdir-ls-ls---parseable-no-args/node_modules/foo
+{CWD}/tap-testdir-ls-ls---parseable-no-args/node_modules/lorem
+{CWD}/tap-testdir-ls-ls---parseable-no-args/node_modules/bar
 `
 
 exports[`test/lib/ls.js TAP ls --parseable resolved points to git ref > should output tree containing git refs 1`] = `
-{CWD}/ls-ls-parseable-resolved-points-to-git-ref
-{CWD}/ls-ls-parseable-resolved-points-to-git-ref/node_modules/abbrev
+{CWD}/tap-testdir-ls-ls---parseable-resolved-points-to-git-ref
+{CWD}/tap-testdir-ls-ls---parseable-resolved-points-to-git-ref/node_modules/abbrev
 `
 
 exports[`test/lib/ls.js TAP ls --parseable unmet optional dep > should output parseable with empty entry for missing optional deps 1`] = `
-{CWD}/ls-ls-parseable-unmet-optional-dep
-{CWD}/ls-ls-parseable-unmet-optional-dep/node_modules/dev-dep
-{CWD}/ls-ls-parseable-unmet-optional-dep/node_modules/lorem
-{CWD}/ls-ls-parseable-unmet-optional-dep/node_modules/optional-dep
-{CWD}/ls-ls-parseable-unmet-optional-dep/node_modules/peer-dep
-{CWD}/ls-ls-parseable-unmet-optional-dep/node_modules/prod-dep
-{CWD}/ls-ls-parseable-unmet-optional-dep/node_modules/foo
-{CWD}/ls-ls-parseable-unmet-optional-dep/node_modules/prod-dep/node_modules/bar
-{CWD}/ls-ls-parseable-unmet-optional-dep/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable-unmet-optional-dep
+{CWD}/tap-testdir-ls-ls---parseable-unmet-optional-dep/node_modules/dev-dep
+{CWD}/tap-testdir-ls-ls---parseable-unmet-optional-dep/node_modules/lorem
+{CWD}/tap-testdir-ls-ls---parseable-unmet-optional-dep/node_modules/optional-dep
+{CWD}/tap-testdir-ls-ls---parseable-unmet-optional-dep/node_modules/peer-dep
+{CWD}/tap-testdir-ls-ls---parseable-unmet-optional-dep/node_modules/prod-dep
+{CWD}/tap-testdir-ls-ls---parseable-unmet-optional-dep/node_modules/foo
+{CWD}/tap-testdir-ls-ls---parseable-unmet-optional-dep/node_modules/prod-dep/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable-unmet-optional-dep/node_modules/bar
 `
 
 exports[`test/lib/ls.js TAP ls --parseable unmet peer dep > should output parseable signaling missing peer dep in problems 1`] = `
-{CWD}/ls-ls-parseable-unmet-peer-dep
-{CWD}/ls-ls-parseable-unmet-peer-dep/node_modules/dev-dep
-{CWD}/ls-ls-parseable-unmet-peer-dep/node_modules/lorem
-{CWD}/ls-ls-parseable-unmet-peer-dep/node_modules/optional-dep
-{CWD}/ls-ls-parseable-unmet-peer-dep/node_modules/peer-dep
-{CWD}/ls-ls-parseable-unmet-peer-dep/node_modules/prod-dep
-{CWD}/ls-ls-parseable-unmet-peer-dep/node_modules/foo
-{CWD}/ls-ls-parseable-unmet-peer-dep/node_modules/prod-dep/node_modules/bar
-{CWD}/ls-ls-parseable-unmet-peer-dep/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable-unmet-peer-dep
+{CWD}/tap-testdir-ls-ls---parseable-unmet-peer-dep/node_modules/dev-dep
+{CWD}/tap-testdir-ls-ls---parseable-unmet-peer-dep/node_modules/lorem
+{CWD}/tap-testdir-ls-ls---parseable-unmet-peer-dep/node_modules/optional-dep
+{CWD}/tap-testdir-ls-ls---parseable-unmet-peer-dep/node_modules/peer-dep
+{CWD}/tap-testdir-ls-ls---parseable-unmet-peer-dep/node_modules/prod-dep
+{CWD}/tap-testdir-ls-ls---parseable-unmet-peer-dep/node_modules/foo
+{CWD}/tap-testdir-ls-ls---parseable-unmet-peer-dep/node_modules/prod-dep/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable-unmet-peer-dep/node_modules/bar
 `
 
 exports[`test/lib/ls.js TAP ls --parseable using aliases > should output tree containing aliases 1`] = `
-{CWD}/ls-ls-parseable-using-aliases
-{CWD}/ls-ls-parseable-using-aliases/node_modules/a
+{CWD}/tap-testdir-ls-ls---parseable-using-aliases
+{CWD}/tap-testdir-ls-ls---parseable-using-aliases/node_modules/a
 `
 
 exports[`test/lib/ls.js TAP ls --parseable with filter arg > should output parseable contaning only occurrences of filtered by package 1`] = `
-{CWD}/ls-ls-parseable-with-filter-arg/node_modules/lorem
+{CWD}/tap-testdir-ls-ls---parseable-with-filter-arg/node_modules/lorem
 `
 
 exports[`test/lib/ls.js TAP ls --parseable with filter arg nested dep > should output parseable contaning only occurrences of filtered package 1`] = `
-{CWD}/ls-ls-parseable-with-filter-arg-nested-dep/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable-with-filter-arg-nested-dep/node_modules/bar
 `
 
 exports[`test/lib/ls.js TAP ls --parseable with missing filter arg > should output parseable output containing no dependencies info 1`] = `
@@ -300,12 +300,12 @@ exports[`test/lib/ls.js TAP ls --parseable with missing filter arg > should outp
 `
 
 exports[`test/lib/ls.js TAP ls --parseable with multiple filter args > should output parseable contaning only occurrences of multiple filtered packages and their ancestors 1`] = `
-{CWD}/ls-ls-parseable-with-multiple-filter-args/node_modules/lorem
-{CWD}/ls-ls-parseable-with-multiple-filter-args/node_modules/bar
+{CWD}/tap-testdir-ls-ls---parseable-with-multiple-filter-args/node_modules/lorem
+{CWD}/tap-testdir-ls-ls---parseable-with-multiple-filter-args/node_modules/bar
 `
 
 exports[`test/lib/ls.js TAP ls --production > should output tree containing production deps 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls--production
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls---production
 +-- lorem@1.0.0
 +-- optional-dep@1.0.0
 \`-- prod-dep@1.0.0
@@ -314,13 +314,13 @@ test-npm-ls@1.0.0 {CWD}/ls-ls--production
 `
 
 exports[`test/lib/ls.js TAP ls broken resolved field > should NOT print git refs in output tree 1`] = `
-npm-broken-resolved-field-test@1.0.0 {CWD}/ls-ls-broken-resolved-field
+npm-broken-resolved-field-test@1.0.0 {CWD}/tap-testdir-ls-ls-broken-resolved-field
 \`-- a@1.0.1
 
 `
 
 exports[`test/lib/ls.js TAP ls colored output > should output tree containing color info 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-colored-output
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-colored-output
 +-- foo@1.0.0 invalid
 | \`-- bar@1.0.0
 +-- UNMET DEPENDENCY ipsum@^1.0.0
@@ -329,7 +329,7 @@ exports[`test/lib/ls.js TAP ls colored output > should output tree containing co
 `
 
 exports[`test/lib/ls.js TAP ls cycle deps > should print tree output containing deduped ref 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-cycle-deps
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-cycle-deps
 \`-- a@1.0.0
   \`-- b@1.0.0
     \`-- a@1.0.0 deduped
@@ -337,7 +337,7 @@ test-npm-ls@1.0.0 {CWD}/ls-ls-cycle-deps
 `
 
 exports[`test/lib/ls.js TAP ls cycle deps with filter args > should print tree output containing deduped ref 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-cycle-deps-with-filter-args
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-cycle-deps-with-filter-args
 \`-- a@1.0.0
   \`-- b@1.0.0
     \`-- a@1.0.0 deduped
@@ -345,7 +345,7 @@ exports[`test/lib/ls.js TAP ls cycle deps with filter args > should print tree o
 `
 
 exports[`test/lib/ls.js TAP ls deduped missing dep > should output parseable signaling missing peer dep in problems 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-deduped-missing-dep
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-deduped-missing-dep
 +-- a@1.0.0
 | \`-- UNMET DEPENDENCY b@^1.0.0 deduped
 \`-- UNMET DEPENDENCY b@^1.0.0
@@ -353,20 +353,20 @@ test-npm-ls@1.0.0 {CWD}/ls-ls-deduped-missing-dep
 `
 
 exports[`test/lib/ls.js TAP ls default --depth value should be 0 > should output tree containing only top-level dependencies 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-default-depth-value-should-be-0
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-default---depth-value-should-be-0
 +-- foo@1.0.0
 \`-- lorem@1.0.0
 
 `
 
 exports[`test/lib/ls.js TAP ls empty location > should print empty result 1`] = `
-{CWD}/ls-ls-empty-location
+{CWD}/tap-testdir-ls-ls-empty-location
 \`-- (empty)
 
 `
 
 exports[`test/lib/ls.js TAP ls extraneous deps > should output containing problems info 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-extraneous-deps
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-extraneous-deps
 +-- foo@1.0.0
 | \`-- bar@1.0.0
 \`-- lorem@1.0.0 extraneous
@@ -374,19 +374,19 @@ test-npm-ls@1.0.0 {CWD}/ls-ls-extraneous-deps
 `
 
 exports[`test/lib/ls.js TAP ls filter pkg arg using depth option > should list a in top-level only 1`] = `
-test-pkg-arg-filter-with-depth-opt@1.0.0 {CWD}/ls-ls-filter-pkg-arg-using-depth-option
+test-pkg-arg-filter-with-depth-opt@1.0.0 {CWD}/tap-testdir-ls-ls-filter-pkg-arg-using-depth-option
 \`-- a@1.0.0
 
 `
 
 exports[`test/lib/ls.js TAP ls filter pkg arg using depth option > should print empty results msg 1`] = `
-test-pkg-arg-filter-with-depth-opt@1.0.0 {CWD}/ls-ls-filter-pkg-arg-using-depth-option
+test-pkg-arg-filter-with-depth-opt@1.0.0 {CWD}/tap-testdir-ls-ls-filter-pkg-arg-using-depth-option
 \`-- (empty)
 
 `
 
 exports[`test/lib/ls.js TAP ls filter pkg arg using depth option > should print expected result 1`] = `
-test-pkg-arg-filter-with-depth-opt@1.0.0 {CWD}/ls-ls-filter-pkg-arg-using-depth-option
+test-pkg-arg-filter-with-depth-opt@1.0.0 {CWD}/tap-testdir-ls-ls-filter-pkg-arg-using-depth-option
 \`-- b@1.0.0
   \`-- c@1.0.0
     \`-- d@1.0.0
@@ -394,7 +394,7 @@ test-pkg-arg-filter-with-depth-opt@1.0.0 {CWD}/ls-ls-filter-pkg-arg-using-depth-
 `
 
 exports[`test/lib/ls.js TAP ls filtering by child of missing dep > should print tree and not duplicate child of missing items 1`] = `
-filter-by-child-of-missing-dep@1.0.0 {CWD}/ls-ls-filtering-by-child-of-missing-dep
+filter-by-child-of-missing-dep@1.0.0 {CWD}/tap-testdir-ls-ls-filtering-by-child-of-missing-dep
 +-- b@1.0.0 extraneous
 | \`-- c@1.0.0 deduped
 +-- c@1.0.0 extraneous
@@ -404,13 +404,13 @@ filter-by-child-of-missing-dep@1.0.0 {CWD}/ls-ls-filtering-by-child-of-missing-d
 `
 
 exports[`test/lib/ls.js TAP ls from and resolved properties > should not be printed in tree output 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-from-and-resolved-properties
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-from-and-resolved-properties
 \`-- simple-output@2.1.1
 
 `
 
 exports[`test/lib/ls.js TAP ls global > should print tree and not mark top-level items extraneous 1`] = `
-{CWD}/ls-ls-global
+{CWD}/tap-testdir-ls-ls-global
 +-- a@1.0.0
 \`-- b@1.0.0
   \`-- c@1.0.0
@@ -418,7 +418,7 @@ exports[`test/lib/ls.js TAP ls global > should print tree and not mark top-level
 `
 
 exports[`test/lib/ls.js TAP ls invalid deduped dep > should output tree signaling mismatching peer dep in problems 1`] = `
-invalid-deduped-dep@1.0.0 {CWD}/ls-ls-invalid-deduped-dep
+invalid-deduped-dep@1.0.0 {CWD}/tap-testdir-ls-ls-invalid-deduped-dep
 +-- a@1.0.0
 | \`-- b@1.0.0 deduped invalid
 \`-- b@1.0.0 invalid
@@ -426,7 +426,7 @@ exports[`test/lib/ls.js TAP ls invalid deduped dep > should output tree signalin
 `
 
 exports[`test/lib/ls.js TAP ls invalid peer dep > should output tree signaling mismatching peer dep in problems 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-invalid-peer-dep
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-invalid-peer-dep
 +-- dev-dep@1.0.0
 | \`-- foo@1.0.0
 |   \`-- bar@1.0.0
@@ -439,33 +439,33 @@ test-npm-ls@1.0.0 {CWD}/ls-ls-invalid-peer-dep
 `
 
 exports[`test/lib/ls.js TAP ls json read problems > should print empty result 1`] = `
-{CWD}/ls-ls-json-read-problems
+{CWD}/tap-testdir-ls-ls-json-read-problems
 \`-- (empty)
 
 `
 
 exports[`test/lib/ls.js TAP ls loading a tree containing workspaces > should filter single workspace 1`] = `
-filter-by-child-of-missing-dep@1.0.0 {CWD}/ls-ls-loading-a-tree-containing-workspaces
-\`-- a@1.0.0 -> {CWD}/ls-ls-loading-a-tree-containing-workspaces/a
+filter-by-child-of-missing-dep@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces
+\`-- a@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/a
 
 `
 
 exports[`test/lib/ls.js TAP ls loading a tree containing workspaces > should list workspaces properly 1`] = `
-filter-by-child-of-missing-dep@1.0.0 {CWD}/ls-ls-loading-a-tree-containing-workspaces
-+-- a@1.0.0 -> {CWD}/ls-ls-loading-a-tree-containing-workspaces/a
+filter-by-child-of-missing-dep@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces
++-- a@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/a
 | \`-- c@1.0.0
-\`-- b@1.0.0 -> {CWD}/ls-ls-loading-a-tree-containing-workspaces/b
+\`-- b@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/b
 
 `
 
 exports[`test/lib/ls.js TAP ls missing package.json > should log all extraneous deps on error msg 1`] = `
-extraneous: bar@1.0.0 {CWD}/ls-ls-missing-package-json/node_modules/bar
-extraneous: foo@1.0.0 {CWD}/ls-ls-missing-package-json/node_modules/foo
-extraneous: lorem@1.0.0 {CWD}/ls-ls-missing-package-json/node_modules/lorem
+extraneous: bar@1.0.0 {CWD}/tap-testdir-ls-ls-missing-package.json/node_modules/bar
+extraneous: foo@1.0.0 {CWD}/tap-testdir-ls-ls-missing-package.json/node_modules/foo
+extraneous: lorem@1.0.0 {CWD}/tap-testdir-ls-ls-missing-package.json/node_modules/lorem
 `
 
 exports[`test/lib/ls.js TAP ls missing package.json > should output tree missing name/version of top-level package 1`] = `
-{CWD}/ls-ls-missing-package-json
+{CWD}/tap-testdir-ls-ls-missing-package.json
 +-- bar@1.0.0 extraneous
 +-- foo@1.0.0 extraneous
 | \`-- bar@1.0.0 deduped
@@ -474,7 +474,7 @@ exports[`test/lib/ls.js TAP ls missing package.json > should output tree missing
 `
 
 exports[`test/lib/ls.js TAP ls missing/invalid/extraneous > should output tree containing missing, invalid, extraneous labels 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-missing-invalid-extraneous
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-missing-invalid-extraneous
 +-- foo@1.0.0 invalid
 | \`-- bar@1.0.0
 +-- UNMET DEPENDENCY ipsum@^1.0.0
@@ -483,7 +483,7 @@ test-npm-ls@1.0.0 {CWD}/ls-ls-missing-invalid-extraneous
 `
 
 exports[`test/lib/ls.js TAP ls no args > should output tree representation of dependencies structure 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-no-args
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-no-args
 +-- foo@1.0.0
 | \`-- bar@1.0.0
 \`-- lorem@1.0.0
@@ -491,21 +491,21 @@ test-npm-ls@1.0.0 {CWD}/ls-ls-no-args
 `
 
 exports[`test/lib/ls.js TAP ls print deduped symlinks > should output tree containing linked deps 1`] = `
-print-deduped-symlinks@1.0.0 {CWD}/ls-ls-print-deduped-symlinks
+print-deduped-symlinks@1.0.0 {CWD}/tap-testdir-ls-ls-print-deduped-symlinks
 +-- a@1.0.0
-| \`-- b@1.0.0 deduped -> {CWD}/ls-ls-print-deduped-symlinks/b
-\`-- b@1.0.0 -> {CWD}/ls-ls-print-deduped-symlinks/b
+| \`-- b@1.0.0 deduped -> {CWD}/tap-testdir-ls-ls-print-deduped-symlinks/b
+\`-- b@1.0.0 -> {CWD}/tap-testdir-ls-ls-print-deduped-symlinks/b
 
 `
 
 exports[`test/lib/ls.js TAP ls resolved points to git ref > should output tree containing git refs 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-resolved-points-to-git-ref
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-resolved-points-to-git-ref
 \`-- abbrev@1.1.1 (git+ssh://git@github.com/isaacs/abbrev-js.git#b8f3a2fc0c3bb8ffd8b0d0072cc6b5a3667e963c)
 
 `
 
 exports[`test/lib/ls.js TAP ls unmet optional dep > should output tree with empty entry for missing optional deps 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-unmet-optional-dep
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-unmet-optional-dep
 +-- dev-dep@1.0.0
 | \`-- foo@1.0.0
 |   \`-- bar@1.0.0
@@ -519,19 +519,19 @@ exports[`test/lib/ls.js TAP ls unmet optional dep > should output tree with empt
 `
 
 exports[`test/lib/ls.js TAP ls unmet peer dep > should output tree signaling missing peer dep in problems 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-unmet-peer-dep
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-unmet-peer-dep
 \`-- UNMET DEPENDENCY peer-dep@*
 
 `
 
 exports[`test/lib/ls.js TAP ls using aliases > should output tree containing aliases 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-using-aliases
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-using-aliases
 \`-- a@npm:b@1.0.0
 
 `
 
 exports[`test/lib/ls.js TAP ls with args and dedupe entries > should print tree output containing deduped ref 1`] = `
-dedupe-entries@1.0.0 {CWD}/ls-ls-with-args-and-dedupe-entries
+dedupe-entries@1.0.0 {CWD}/tap-testdir-ls-ls-with-args-and-dedupe-entries
 +-- @npmcli/a@1.0.0
 | \`-- @npmcli/b@1.1.2 deduped
 +-- @npmcli/b@1.1.2
@@ -541,7 +541,7 @@ exports[`test/lib/ls.js TAP ls with args and dedupe entries > should print tree
 `
 
 exports[`test/lib/ls.js TAP ls with args and different order of items > should print tree output containing deduped ref 1`] = `
-dedupe-entries@1.0.0 {CWD}/ls-ls-with-args-and-different-order-of-items
+dedupe-entries@1.0.0 {CWD}/tap-testdir-ls-ls-with-args-and-different-order-of-items
 +-- @npmcli/a@1.0.0
 | \`-- @npmcli/c@1.0.0 deduped
 +-- @npmcli/b@1.1.2
@@ -551,32 +551,32 @@ dedupe-entries@1.0.0 {CWD}/ls-ls-with-args-and-different-order-of-items
 `
 
 exports[`test/lib/ls.js TAP ls with dot filter arg > should output tree contaning only occurrences of filtered by package and colored output 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-with-dot-filter-arg
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-with-dot-filter-arg
 \`-- (empty)
 
 `
 
 exports[`test/lib/ls.js TAP ls with filter arg > should output tree contaning only occurrences of filtered by package and colored output 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-with-filter-arg
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-with-filter-arg
 \`-- lorem@1.0.0
 
 `
 
 exports[`test/lib/ls.js TAP ls with filter arg nested dep > should output tree contaning only occurrences of filtered package and its ancestors 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-with-filter-arg-nested-dep
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-with-filter-arg-nested-dep
 \`-- foo@1.0.0
   \`-- bar@1.0.0
 
 `
 
 exports[`test/lib/ls.js TAP ls with missing filter arg > should output tree containing no dependencies info 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-with-missing-filter-arg
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-with-missing-filter-arg
 \`-- (empty)
 
 `
 
 exports[`test/lib/ls.js TAP ls with multiple filter args > should output tree contaning only occurrences of multiple filtered packages and their ancestors 1`] = `
-test-npm-ls@1.0.0 {CWD}/ls-ls-with-multiple-filter-args
+test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-with-multiple-filter-args
 +-- foo@1.0.0
 | \`-- bar@1.0.0
 \`-- lorem@1.0.0
@@ -584,7 +584,7 @@ test-npm-ls@1.0.0 {CWD}/ls-ls-with-multiple-filter-args
 `
 
 exports[`test/lib/ls.js TAP ls with no args dedupe entries > should print tree output containing deduped ref 1`] = `
-dedupe-entries@1.0.0 {CWD}/ls-ls-with-no-args-dedupe-entries
+dedupe-entries@1.0.0 {CWD}/tap-testdir-ls-ls-with-no-args-dedupe-entries
 +-- @npmcli/a@1.0.0
 | \`-- @npmcli/b@1.1.2 deduped
 +-- @npmcli/b@1.1.2
@@ -594,7 +594,7 @@ dedupe-entries@1.0.0 {CWD}/ls-ls-with-no-args-dedupe-entries
 `
 
 exports[`test/lib/ls.js TAP ls with no args dedupe entries and not displaying all > should print tree output containing deduped ref 1`] = `
-dedupe-entries@1.0.0 {CWD}/ls-ls-with-no-args-dedupe-entries-and-not-displaying-all
+dedupe-entries@1.0.0 {CWD}/tap-testdir-ls-ls-with-no-args-dedupe-entries-and-not-displaying-all
 +-- @npmcli/a@1.0.0
 +-- @npmcli/b@1.1.2
 \`-- @npmcli/c@1.0.0
diff --git a/tap-snapshots/test/lib/outdated.js.test.cjs b/tap-snapshots/test/lib/outdated.js.test.cjs
new file mode 100644
index 0000000000000..e57d7110b2275
--- /dev/null
+++ b/tap-snapshots/test/lib/outdated.js.test.cjs
@@ -0,0 +1,154 @@
+/* IMPORTANT
+ * This snapshot file is auto-generated, but designed for humans.
+ * It should be checked into source control and tracked carefully.
+ * Re-generate by setting TAP_SNAPSHOT=1 and running tests.
+ * Make sure to inspect the output below.  Do not ignore changes!
+ */
+'use strict'
+exports[`test/lib/outdated.js TAP should display outdated deps outdated --all > must match snapshot 1`] = `
+
+Package  Current  Wanted  Latest  Location            Depended by
+alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  tap-testdir-outdated-should-display-outdated-deps
+beta       1.0.0   1.0.1   1.0.1  node_modules/beta   tap-testdir-outdated-should-display-outdated-deps
+gamma      1.0.1   1.0.1   2.0.0  node_modules/gamma  tap-testdir-outdated-should-display-outdated-deps
+theta    MISSING   1.0.1   1.0.1  -                   tap-testdir-outdated-should-display-outdated-deps
+`
+
+exports[`test/lib/outdated.js TAP should display outdated deps outdated --json --long > must match snapshot 1`] = `
+
+{
+  "alpha": {
+    "current": "1.0.0",
+    "wanted": "1.0.1",
+    "latest": "1.0.1",
+    "dependent": "tap-testdir-outdated-should-display-outdated-deps",
+    "location": "{CWD}/test/lib/tap-testdir-outdated-should-display-outdated-deps/node_modules/alpha",
+    "type": "dependencies"
+  },
+  "beta": {
+    "current": "1.0.0",
+    "wanted": "1.0.1",
+    "latest": "1.0.1",
+    "dependent": "tap-testdir-outdated-should-display-outdated-deps",
+    "location": "{CWD}/test/lib/tap-testdir-outdated-should-display-outdated-deps/node_modules/beta",
+    "type": "peerDependencies"
+  },
+  "gamma": {
+    "current": "1.0.1",
+    "wanted": "1.0.1",
+    "latest": "2.0.0",
+    "dependent": "tap-testdir-outdated-should-display-outdated-deps",
+    "location": "{CWD}/test/lib/tap-testdir-outdated-should-display-outdated-deps/node_modules/gamma",
+    "type": "dependencies"
+  },
+  "theta": {
+    "wanted": "1.0.1",
+    "latest": "1.0.1",
+    "dependent": "tap-testdir-outdated-should-display-outdated-deps",
+    "type": "dependencies"
+  }
+}
+`
+
+exports[`test/lib/outdated.js TAP should display outdated deps outdated --json > must match snapshot 1`] = `
+
+{
+  "alpha": {
+    "current": "1.0.0",
+    "wanted": "1.0.1",
+    "latest": "1.0.1",
+    "dependent": "tap-testdir-outdated-should-display-outdated-deps",
+    "location": "{CWD}/test/lib/tap-testdir-outdated-should-display-outdated-deps/node_modules/alpha"
+  },
+  "beta": {
+    "current": "1.0.0",
+    "wanted": "1.0.1",
+    "latest": "1.0.1",
+    "dependent": "tap-testdir-outdated-should-display-outdated-deps",
+    "location": "{CWD}/test/lib/tap-testdir-outdated-should-display-outdated-deps/node_modules/beta"
+  },
+  "gamma": {
+    "current": "1.0.1",
+    "wanted": "1.0.1",
+    "latest": "2.0.0",
+    "dependent": "tap-testdir-outdated-should-display-outdated-deps",
+    "location": "{CWD}/test/lib/tap-testdir-outdated-should-display-outdated-deps/node_modules/gamma"
+  },
+  "theta": {
+    "wanted": "1.0.1",
+    "latest": "1.0.1",
+    "dependent": "tap-testdir-outdated-should-display-outdated-deps"
+  }
+}
+`
+
+exports[`test/lib/outdated.js TAP should display outdated deps outdated --long > must match snapshot 1`] = `
+
+Package  Current  Wanted  Latest  Location            Depended by                                        Package Type      Homepage
+alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  tap-testdir-outdated-should-display-outdated-deps  dependencies
+beta       1.0.0   1.0.1   1.0.1  node_modules/beta   tap-testdir-outdated-should-display-outdated-deps  peerDependencies
+gamma      1.0.1   1.0.1   2.0.0  node_modules/gamma  tap-testdir-outdated-should-display-outdated-deps  dependencies
+theta    MISSING   1.0.1   1.0.1  -                   tap-testdir-outdated-should-display-outdated-deps  dependencies
+`
+
+exports[`test/lib/outdated.js TAP should display outdated deps outdated --omit=dev --omit=peer > must match snapshot 1`] = `
+
+Package  Current  Wanted  Latest  Location            Depended by
+alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  tap-testdir-outdated-should-display-outdated-deps
+gamma      1.0.1   1.0.1   2.0.0  node_modules/gamma  tap-testdir-outdated-should-display-outdated-deps
+theta    MISSING   1.0.1   1.0.1  -                   tap-testdir-outdated-should-display-outdated-deps
+`
+
+exports[`test/lib/outdated.js TAP should display outdated deps outdated --omit=dev > must match snapshot 1`] = `
+
+Package  Current  Wanted  Latest  Location            Depended by
+alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  tap-testdir-outdated-should-display-outdated-deps
+beta       1.0.0   1.0.1   1.0.1  node_modules/beta   tap-testdir-outdated-should-display-outdated-deps
+gamma      1.0.1   1.0.1   2.0.0  node_modules/gamma  tap-testdir-outdated-should-display-outdated-deps
+theta    MISSING   1.0.1   1.0.1  -                   tap-testdir-outdated-should-display-outdated-deps
+`
+
+exports[`test/lib/outdated.js TAP should display outdated deps outdated --omit=prod > must match snapshot 1`] = `
+
+Package  Current  Wanted  Latest  Location            Depended by
+alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  tap-testdir-outdated-should-display-outdated-deps
+beta       1.0.0   1.0.1   1.0.1  node_modules/beta   tap-testdir-outdated-should-display-outdated-deps
+gamma      1.0.1   1.0.1   2.0.0  node_modules/gamma  tap-testdir-outdated-should-display-outdated-deps
+`
+
+exports[`test/lib/outdated.js TAP should display outdated deps outdated --parseable --long > must match snapshot 1`] = `
+
+{CWD}/test/lib/tap-testdir-outdated-should-display-outdated-deps/node_modules/alpha:alpha@1.0.1:alpha@1.0.0:alpha@1.0.1:tap-testdir-outdated-should-display-outdated-deps:dependencies:
+{CWD}/test/lib/tap-testdir-outdated-should-display-outdated-deps/node_modules/beta:beta@1.0.1:beta@1.0.0:beta@1.0.1:tap-testdir-outdated-should-display-outdated-deps:peerDependencies:
+{CWD}/test/lib/tap-testdir-outdated-should-display-outdated-deps/node_modules/gamma:gamma@1.0.1:gamma@1.0.1:gamma@2.0.0:tap-testdir-outdated-should-display-outdated-deps:dependencies:
+:theta@1.0.1:MISSING:theta@1.0.1:tap-testdir-outdated-should-display-outdated-deps:dependencies:
+`
+
+exports[`test/lib/outdated.js TAP should display outdated deps outdated --parseable > must match snapshot 1`] = `
+
+{CWD}/test/lib/tap-testdir-outdated-should-display-outdated-deps/node_modules/alpha:alpha@1.0.1:alpha@1.0.0:alpha@1.0.1:tap-testdir-outdated-should-display-outdated-deps
+{CWD}/test/lib/tap-testdir-outdated-should-display-outdated-deps/node_modules/beta:beta@1.0.1:beta@1.0.0:beta@1.0.1:tap-testdir-outdated-should-display-outdated-deps
+{CWD}/test/lib/tap-testdir-outdated-should-display-outdated-deps/node_modules/gamma:gamma@1.0.1:gamma@1.0.1:gamma@2.0.0:tap-testdir-outdated-should-display-outdated-deps
+:theta@1.0.1:MISSING:theta@1.0.1:tap-testdir-outdated-should-display-outdated-deps
+`
+
+exports[`test/lib/outdated.js TAP should display outdated deps outdated > must match snapshot 1`] = `
+
+Package  Current  Wanted  Latest  Location            Depended by
+alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  tap-testdir-outdated-should-display-outdated-deps
+beta       1.0.0   1.0.1   1.0.1  node_modules/beta   tap-testdir-outdated-should-display-outdated-deps
+gamma      1.0.1   1.0.1   2.0.0  node_modules/gamma  tap-testdir-outdated-should-display-outdated-deps
+theta    MISSING   1.0.1   1.0.1  -                   tap-testdir-outdated-should-display-outdated-deps
+`
+
+exports[`test/lib/outdated.js TAP should display outdated deps outdated global > must match snapshot 1`] = `
+
+Package  Current  Wanted  Latest  Location            Depended by
+alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  global
+`
+
+exports[`test/lib/outdated.js TAP should display outdated deps outdated specific dep > must match snapshot 1`] = `
+
+Package  Current  Wanted  Latest  Location            Depended by
+alpha      1.0.0   1.0.1   1.0.1  node_modules/alpha  tap-testdir-outdated-should-display-outdated-deps
+`
diff --git a/tap-snapshots/test-lib-owner.js-TAP.test.js b/tap-snapshots/test/lib/owner.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-owner.js-TAP.test.js
rename to tap-snapshots/test/lib/owner.js.test.cjs
diff --git a/tap-snapshots/test-lib-profile.js-TAP.test.js b/tap-snapshots/test/lib/profile.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-profile.js-TAP.test.js
rename to tap-snapshots/test/lib/profile.js.test.cjs
diff --git a/tap-snapshots/test-lib-publish.js-TAP.test.js b/tap-snapshots/test/lib/publish.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-publish.js-TAP.test.js
rename to tap-snapshots/test/lib/publish.js.test.cjs
diff --git a/tap-snapshots/test-lib-search.js-TAP.test.js b/tap-snapshots/test/lib/search.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-search.js-TAP.test.js
rename to tap-snapshots/test/lib/search.js.test.cjs
diff --git a/tap-snapshots/test-lib-stars.js-TAP.test.js b/tap-snapshots/test/lib/stars.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-stars.js-TAP.test.js
rename to tap-snapshots/test/lib/stars.js.test.cjs
diff --git a/tap-snapshots/test-lib-team.js-TAP.test.js b/tap-snapshots/test/lib/team.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-team.js-TAP.test.js
rename to tap-snapshots/test/lib/team.js.test.cjs
diff --git a/tap-snapshots/test-lib-utils-cmd-list.js-TAP.test.js b/tap-snapshots/test/lib/utils/cmd-list.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-utils-cmd-list.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/cmd-list.js.test.cjs
diff --git a/tap-snapshots/test-lib-utils-config-definition.js-TAP.test.js b/tap-snapshots/test/lib/utils/config/definition.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-utils-config-definition.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/config/definition.js.test.cjs
diff --git a/tap-snapshots/test-lib-utils-config-definitions.js-TAP.test.js b/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-utils-config-definitions.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/config/definitions.js.test.cjs
diff --git a/tap-snapshots/test-lib-utils-config-describe-all.js-TAP.test.js b/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-utils-config-describe-all.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs
diff --git a/tap-snapshots/test-lib-utils-config-index.js-TAP.test.js b/tap-snapshots/test/lib/utils/config/index.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-utils-config-index.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/config/index.js.test.cjs
diff --git a/tap-snapshots/test-lib-utils-error-handler.js-TAP.test.js b/tap-snapshots/test/lib/utils/error-handler.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-utils-error-handler.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/error-handler.js.test.cjs
diff --git a/tap-snapshots/test-lib-utils-error-message.js-TAP.test.js b/tap-snapshots/test/lib/utils/error-message.js.test.cjs
similarity index 67%
rename from tap-snapshots/test-lib-utils-error-message.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/error-message.js.test.cjs
index bcf5144499f24..7b02dbd9aaa65 100644
--- a/tap-snapshots/test-lib-utils-error-message.js-TAP.test.js
+++ b/tap-snapshots/test/lib/utils/error-message.js.test.cjs
@@ -28,7 +28,10 @@ Object {
     ],
     Array [
       "404",
-      "\\nNote that you can also install from a",
+      String(
+        
+        Note that you can also install from a
+      ),
     ],
     Array [
       "404",
@@ -67,7 +70,10 @@ Object {
     ],
     Array [
       "404",
-      "\\nNote that you can also install from a",
+      String(
+        
+        Note that you can also install from a
+      ),
     ],
     Array [
       "404",
@@ -113,7 +119,10 @@ Object {
     ],
     Array [
       "404",
-      "\\nNote that you can also install from a",
+      String(
+        
+        Note that you can also install from a
+      ),
     ],
     Array [
       "404",
@@ -134,7 +143,11 @@ Object {
   "detail": Array [
     Array [
       "notsup",
-      "Not compatible with your version of node/npm: some@package\\nRequired: undefined\\nActual:   {\\"npm\\":\\"123.69.420-npm\\",\\"node\\":\\"99.99.99\\"}",
+      String(
+        Not compatible with your version of node/npm: some@package
+        Required: undefined
+        Actual:   {"npm":"123.69.420-npm","node":"99.99.99"}
+      ),
     ],
   ],
   "summary": Array [
@@ -155,7 +168,12 @@ Object {
   "detail": Array [
     Array [
       "notsup",
-      "Valid OS:    !yours,mine\\nValid Arch:  x420,x69\\nActual OS:   posix\\nActual Arch: x64",
+      String(
+        Valid OS:    !yours,mine
+        Valid Arch:  x420,x69
+        Actual OS:   posix
+        Actual Arch: x64
+      ),
     ],
   ],
   "summary": Array [
@@ -172,7 +190,12 @@ Object {
   "detail": Array [
     Array [
       "notsup",
-      "Valid OS:    !yours\\nValid Arch:  x420\\nActual OS:   posix\\nActual Arch: x64",
+      String(
+        Valid OS:    !yours
+        Valid Arch:  x420
+        Actual OS:   posix
+        Actual Arch: x64
+      ),
     ],
   ],
   "summary": Array [
@@ -246,7 +269,15 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nThe operation was rejected by your operating system.\\nIt is likely you do not have the permissions to access this file as the current user\\n\\nIf you believe this might be a permissions issue, please double-check the\\npermissions of the file and its containing directories, or try running\\nthe command again as root/Administrator.",
+      String(
+        
+        The operation was rejected by your operating system.
+        It is likely you do not have the permissions to access this file as the current user
+        
+        If you believe this might be a permissions issue, please double-check the
+        permissions of the file and its containing directories, or try running
+        the command again as root/Administrator.
+      ),
     ],
   ],
   "summary": Array [
@@ -271,7 +302,15 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nThe operation was rejected by your operating system.\\nIt is likely you do not have the permissions to access this file as the current user\\n\\nIf you believe this might be a permissions issue, please double-check the\\npermissions of the file and its containing directories, or try running\\nthe command again as root/Administrator.",
+      String(
+        
+        The operation was rejected by your operating system.
+        It is likely you do not have the permissions to access this file as the current user
+        
+        If you believe this might be a permissions issue, please double-check the
+        permissions of the file and its containing directories, or try running
+        the command again as root/Administrator.
+      ),
     ],
   ],
   "summary": Array [
@@ -296,7 +335,15 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nThe operation was rejected by your operating system.\\nIt is likely you do not have the permissions to access this file as the current user\\n\\nIf you believe this might be a permissions issue, please double-check the\\npermissions of the file and its containing directories, or try running\\nthe command again as root/Administrator.",
+      String(
+        
+        The operation was rejected by your operating system.
+        It is likely you do not have the permissions to access this file as the current user
+        
+        If you believe this might be a permissions issue, please double-check the
+        permissions of the file and its containing directories, or try running
+        the command again as root/Administrator.
+      ),
     ],
   ],
   "summary": Array [
@@ -321,7 +368,15 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nThe operation was rejected by your operating system.\\nIt is likely you do not have the permissions to access this file as the current user\\n\\nIf you believe this might be a permissions issue, please double-check the\\npermissions of the file and its containing directories, or try running\\nthe command again as root/Administrator.",
+      String(
+        
+        The operation was rejected by your operating system.
+        It is likely you do not have the permissions to access this file as the current user
+        
+        If you believe this might be a permissions issue, please double-check the
+        permissions of the file and its containing directories, or try running
+        the command again as root/Administrator.
+      ),
     ],
   ],
   "summary": Array [
@@ -346,7 +401,15 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nThe operation was rejected by your operating system.\\nIt is likely you do not have the permissions to access this file as the current user\\n\\nIf you believe this might be a permissions issue, please double-check the\\npermissions of the file and its containing directories, or try running\\nthe command again as root/Administrator.",
+      String(
+        
+        The operation was rejected by your operating system.
+        It is likely you do not have the permissions to access this file as the current user
+        
+        If you believe this might be a permissions issue, please double-check the
+        permissions of the file and its containing directories, or try running
+        the command again as root/Administrator.
+      ),
     ],
   ],
   "summary": Array [
@@ -372,7 +435,14 @@ Object {
   "summary": Array [
     Array [
       "",
-      "\\nYour cache folder contains root-owned files, due to a bug in\\nprevious versions of npm which has since been addressed.\\n\\nTo permanently fix this problem, please run:\\n  sudo chown -R 69:420 \\"/some/cache/dir\\"",
+      String(
+        
+        Your cache folder contains root-owned files, due to a bug in
+        previous versions of npm which has since been addressed.
+        
+        To permanently fix this problem, please run:
+          sudo chown -R 69:420 "/some/cache/dir"
+      ),
     ],
   ],
 }
@@ -392,7 +462,14 @@ Object {
   "summary": Array [
     Array [
       "",
-      "\\nYour cache folder contains root-owned files, due to a bug in\\nprevious versions of npm which has since been addressed.\\n\\nTo permanently fix this problem, please run:\\n  sudo chown -R 69:420 \\"/some/cache/dir\\"",
+      String(
+        
+        Your cache folder contains root-owned files, due to a bug in
+        previous versions of npm which has since been addressed.
+        
+        To permanently fix this problem, please run:
+          sudo chown -R 69:420 "/some/cache/dir"
+      ),
     ],
   ],
 }
@@ -412,7 +489,14 @@ Object {
   "summary": Array [
     Array [
       "",
-      "\\nYour cache folder contains root-owned files, due to a bug in\\nprevious versions of npm which has since been addressed.\\n\\nTo permanently fix this problem, please run:\\n  sudo chown -R 69:420 \\"/some/cache/dir\\"",
+      String(
+        
+        Your cache folder contains root-owned files, due to a bug in
+        previous versions of npm which has since been addressed.
+        
+        To permanently fix this problem, please run:
+          sudo chown -R 69:420 "/some/cache/dir"
+      ),
     ],
   ],
 }
@@ -431,7 +515,16 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nThe operation was rejected by your operating system.\\nIt's possible that the file was already in use (by a text editor or antivirus),\\nor that you lack permissions to access it.\\n\\nIf you believe this might be a permissions issue, please double-check the\\npermissions of the file and its containing directories, or try running\\nthe command again as root/Administrator.",
+      String(
+        
+        The operation was rejected by your operating system.
+        It's possible that the file was already in use (by a text editor or antivirus),
+        or that you lack permissions to access it.
+        
+        If you believe this might be a permissions issue, please double-check the
+        permissions of the file and its containing directories, or try running
+        the command again as root/Administrator.
+      ),
     ],
   ],
   "summary": Array [
@@ -456,7 +549,16 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nThe operation was rejected by your operating system.\\nIt's possible that the file was already in use (by a text editor or antivirus),\\nor that you lack permissions to access it.\\n\\nIf you believe this might be a permissions issue, please double-check the\\npermissions of the file and its containing directories, or try running\\nthe command again as root/Administrator.",
+      String(
+        
+        The operation was rejected by your operating system.
+        It's possible that the file was already in use (by a text editor or antivirus),
+        or that you lack permissions to access it.
+        
+        If you believe this might be a permissions issue, please double-check the
+        permissions of the file and its containing directories, or try running
+        the command again as root/Administrator.
+      ),
     ],
   ],
   "summary": Array [
@@ -481,7 +583,16 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nThe operation was rejected by your operating system.\\nIt's possible that the file was already in use (by a text editor or antivirus),\\nor that you lack permissions to access it.\\n\\nIf you believe this might be a permissions issue, please double-check the\\npermissions of the file and its containing directories, or try running\\nthe command again as root/Administrator.",
+      String(
+        
+        The operation was rejected by your operating system.
+        It's possible that the file was already in use (by a text editor or antivirus),
+        or that you lack permissions to access it.
+        
+        If you believe this might be a permissions issue, please double-check the
+        permissions of the file and its containing directories, or try running
+        the command again as root/Administrator.
+      ),
     ],
   ],
   "summary": Array [
@@ -506,7 +617,16 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nThe operation was rejected by your operating system.\\nIt's possible that the file was already in use (by a text editor or antivirus),\\nor that you lack permissions to access it.\\n\\nIf you believe this might be a permissions issue, please double-check the\\npermissions of the file and its containing directories, or try running\\nthe command again as root/Administrator.",
+      String(
+        
+        The operation was rejected by your operating system.
+        It's possible that the file was already in use (by a text editor or antivirus),
+        or that you lack permissions to access it.
+        
+        If you believe this might be a permissions issue, please double-check the
+        permissions of the file and its containing directories, or try running
+        the command again as root/Administrator.
+      ),
     ],
   ],
   "summary": Array [
@@ -531,7 +651,16 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nThe operation was rejected by your operating system.\\nIt's possible that the file was already in use (by a text editor or antivirus),\\nor that you lack permissions to access it.\\n\\nIf you believe this might be a permissions issue, please double-check the\\npermissions of the file and its containing directories, or try running\\nthe command again as root/Administrator.",
+      String(
+        
+        The operation was rejected by your operating system.
+        It's possible that the file was already in use (by a text editor or antivirus),
+        or that you lack permissions to access it.
+        
+        If you believe this might be a permissions issue, please double-check the
+        permissions of the file and its containing directories, or try running
+        the command again as root/Administrator.
+      ),
     ],
   ],
   "summary": Array [
@@ -556,7 +685,16 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nThe operation was rejected by your operating system.\\nIt's possible that the file was already in use (by a text editor or antivirus),\\nor that you lack permissions to access it.\\n\\nIf you believe this might be a permissions issue, please double-check the\\npermissions of the file and its containing directories, or try running\\nthe command again as root/Administrator.",
+      String(
+        
+        The operation was rejected by your operating system.
+        It's possible that the file was already in use (by a text editor or antivirus),
+        or that you lack permissions to access it.
+        
+        If you believe this might be a permissions issue, please double-check the
+        permissions of the file and its containing directories, or try running
+        the command again as root/Administrator.
+      ),
     ],
   ],
   "summary": Array [
@@ -581,7 +719,16 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nThe operation was rejected by your operating system.\\nIt's possible that the file was already in use (by a text editor or antivirus),\\nor that you lack permissions to access it.\\n\\nIf you believe this might be a permissions issue, please double-check the\\npermissions of the file and its containing directories, or try running\\nthe command again as root/Administrator.",
+      String(
+        
+        The operation was rejected by your operating system.
+        It's possible that the file was already in use (by a text editor or antivirus),
+        or that you lack permissions to access it.
+        
+        If you believe this might be a permissions issue, please double-check the
+        permissions of the file and its containing directories, or try running
+        the command again as root/Administrator.
+      ),
     ],
   ],
   "summary": Array [
@@ -606,7 +753,16 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nThe operation was rejected by your operating system.\\nIt's possible that the file was already in use (by a text editor or antivirus),\\nor that you lack permissions to access it.\\n\\nIf you believe this might be a permissions issue, please double-check the\\npermissions of the file and its containing directories, or try running\\nthe command again as root/Administrator.",
+      String(
+        
+        The operation was rejected by your operating system.
+        It's possible that the file was already in use (by a text editor or antivirus),
+        or that you lack permissions to access it.
+        
+        If you believe this might be a permissions issue, please double-check the
+        permissions of the file and its containing directories, or try running
+        the command again as root/Administrator.
+      ),
     ],
   ],
   "summary": Array [
@@ -695,7 +851,11 @@ Object {
   "detail": Array [
     Array [
       "",
-      "You can provide a one-time password by passing --otp= to the command you ran.\\nIf you already provided a one-time password then it is likely that you either typoed\\nit, or it timed out. Please try again.",
+      String(
+        You can provide a one-time password by passing --otp= to the command you ran.
+        If you already provided a one-time password then it is likely that you either typoed
+        it, or it timed out. Please try again.
+      ),
     ],
   ],
   "summary": Array [
@@ -712,7 +872,11 @@ Object {
   "detail": Array [
     Array [
       "",
-      "You can provide a one-time password by passing --otp= to the command you ran.\\nIf you already provided a one-time password then it is likely that you either typoed\\nit, or it timed out. Please try again.",
+      String(
+        You can provide a one-time password by passing --otp= to the command you ran.
+        If you already provided a one-time password then it is likely that you either typoed
+        it, or it timed out. Please try again.
+      ),
     ],
   ],
   "summary": Array [
@@ -729,7 +893,17 @@ Object {
   "detail": Array [
     Array [
       "",
-      "If you were trying to login, change your password, create an\\nauthentication token or enable two-factor authentication then\\nthat means you likely typed your password in incorrectly.\\nPlease try again, or recover your password at:\\n    https://www.npmjs.com/forgot\\n\\nIf you were doing some other operation then your saved credentials are\\nprobably out of date. To correct this please try logging in again with:\\n    npm login",
+      String(
+        If you were trying to login, change your password, create an
+        authentication token or enable two-factor authentication then
+        that means you likely typed your password in incorrectly.
+        Please try again, or recover your password at:
+            https://www.npmjs.com/forgot
+        
+        If you were doing some other operation then your saved credentials are
+        probably out of date. To correct this please try logging in again with:
+            npm login
+      ),
     ],
   ],
   "summary": Array [
@@ -746,7 +920,10 @@ Object {
   "detail": Array [
     Array [
       "",
-      "To correct this please trying logging in again with:\\n    npm login",
+      String(
+        To correct this please trying logging in again with:
+            npm login
+      ),
     ],
   ],
   "summary": Array [
@@ -820,7 +997,13 @@ Object {
   "detail": Array [
     Array [
       "network",
-      "This is a problem related to network connectivity.\\nIn most cases you are behind a proxy or have bad network settings.\\n\\nIf you are behind a proxy, please make sure that the\\n'proxy' config is set properly.  See: 'npm help config'",
+      String(
+        This is a problem related to network connectivity.
+        In most cases you are behind a proxy or have bad network settings.
+        
+        If you are behind a proxy, please make sure that the
+        'proxy' config is set properly.  See: 'npm help config'
+      ),
     ],
   ],
   "summary": Array [
@@ -837,7 +1020,13 @@ Object {
   "detail": Array [
     Array [
       "network",
-      "This is a problem related to network connectivity.\\nIn most cases you are behind a proxy or have bad network settings.\\n\\nIf you are behind a proxy, please make sure that the\\n'proxy' config is set properly.  See: 'npm help config'",
+      String(
+        This is a problem related to network connectivity.
+        In most cases you are behind a proxy or have bad network settings.
+        
+        If you are behind a proxy, please make sure that the
+        'proxy' config is set properly.  See: 'npm help config'
+      ),
     ],
   ],
   "summary": Array [
@@ -854,7 +1043,13 @@ Object {
   "detail": Array [
     Array [
       "network",
-      "This is a problem related to network connectivity.\\nIn most cases you are behind a proxy or have bad network settings.\\n\\nIf you are behind a proxy, please make sure that the\\n'proxy' config is set properly.  See: 'npm help config'",
+      String(
+        This is a problem related to network connectivity.
+        In most cases you are behind a proxy or have bad network settings.
+        
+        If you are behind a proxy, please make sure that the
+        'proxy' config is set properly.  See: 'npm help config'
+      ),
     ],
   ],
   "summary": Array [
@@ -871,7 +1066,11 @@ Object {
   "detail": Array [
     Array [
       "notsup",
-      "Not compatible with your version of node/npm: some@package\\nRequired: undefined\\nActual:   {\\"npm\\":\\"123.69.420-npm\\",\\"node\\":\\"123.69.420-node\\"}",
+      String(
+        Not compatible with your version of node/npm: some@package
+        Required: undefined
+        Actual:   {"npm":"123.69.420-npm","node":"123.69.420-node"}
+      ),
     ],
   ],
   "summary": Array [
@@ -892,7 +1091,10 @@ Object {
   "detail": Array [
     Array [
       "nospc",
-      "There appears to be insufficient space on your system to finish.\\nClear up some disk space and try again.",
+      String(
+        There appears to be insufficient space on your system to finish.
+        Clear up some disk space and try again.
+      ),
     ],
   ],
   "summary": Array [
@@ -909,7 +1111,10 @@ Object {
   "detail": Array [
     Array [
       "rofs",
-      "Often virtualized file systems, or other file systems\\nthat don't support symlinks, give this error.",
+      String(
+        Often virtualized file systems, or other file systems
+        that don't support symlinks, give this error.
+      ),
     ],
   ],
   "summary": Array [
@@ -926,7 +1131,11 @@ Object {
   "detail": Array [
     Array [
       "enoent",
-      "This is related to npm not being able to find a file.\\n\\nCheck if the file '/some/file' is present.",
+      String(
+        This is related to npm not being able to find a file.
+        
+        Check if the file '/some/file' is present.
+      ),
     ],
   ],
   "summary": Array [
@@ -943,7 +1152,10 @@ Object {
   "detail": Array [
     Array [
       "typeerror",
-      "This is an error with npm itself. Please report this error at:\\n    https://github.com/npm/cli/issues",
+      String(
+        This is an error with npm itself. Please report this error at:
+            https://github.com/npm/cli/issues
+      ),
     ],
   ],
   "summary": Array [
@@ -960,7 +1172,10 @@ Object {
   "detail": Array [
     Array [
       "typeerror",
-      "This is an error with npm itself. Please report this error at:\\n    https://github.com/npm/cli/issues",
+      String(
+        This is an error with npm itself. Please report this error at:
+            https://github.com/npm/cli/issues
+      ),
     ],
   ],
   "summary": Array [
@@ -977,7 +1192,10 @@ Object {
   "detail": Array [
     Array [
       "typeerror",
-      "This is an error with npm itself. Please report this error at:\\n    https://github.com/npm/cli/issues",
+      String(
+        This is an error with npm itself. Please report this error at:
+            https://github.com/npm/cli/issues
+      ),
     ],
   ],
   "summary": Array [
@@ -1015,7 +1233,10 @@ Object {
   "detail": Array [
     Array [
       "typeerror",
-      "This is an error with npm itself. Please report this error at:\\n    https://github.com/npm/cli/issues",
+      String(
+        This is an error with npm itself. Please report this error at:
+            https://github.com/npm/cli/issues
+      ),
     ],
   ],
   "summary": Array [
@@ -1032,7 +1253,10 @@ Object {
   "detail": Array [
     Array [
       "notarget",
-      "In most cases you or one of your dependencies are requesting\\na package version that doesn't exist.",
+      String(
+        In most cases you or one of your dependencies are requesting
+        a package version that doesn't exist.
+      ),
     ],
   ],
   "summary": Array [
@@ -1049,7 +1273,11 @@ Object {
   "detail": Array [
     Array [
       "403",
-      "In most cases, you or one of your dependencies are requesting\\na package version that is forbidden by your security policy, or\\non a server you do not have access to.",
+      String(
+        In most cases, you or one of your dependencies are requesting
+        a package version that is forbidden by your security policy, or
+        on a server you do not have access to.
+      ),
     ],
   ],
   "summary": Array [
@@ -1066,7 +1294,11 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nIf you are behind a proxy, please make sure that the\\n'proxy' config is set properly.  See: 'npm help config'",
+      String(
+        
+        If you are behind a proxy, please make sure that the
+        'proxy' config is set properly.  See: 'npm help config'
+      ),
     ],
   ],
   "summary": Array [
@@ -1088,7 +1320,11 @@ Object {
   "detail": Array [
     Array [
       "",
-      "\\nFailed using git.\\nPlease check if you have git installed and in your PATH.",
+      String(
+        
+        Failed using git.
+        Please check if you have git installed and in your PATH.
+      ),
     ],
   ],
   "summary": Array [
@@ -1134,7 +1370,10 @@ Object {
   "detail": Array [
     Array [
       "git",
-      "Refusing to remove it. Update manually,\\nor move it out of the way first.",
+      String(
+        Refusing to remove it. Update manually,
+        or move it out of the way first.
+      ),
     ],
   ],
   "summary": Array [
@@ -1197,7 +1436,13 @@ Object {
   "detail": Array [
     Array [
       "network",
-      "This is a problem related to network connectivity.\\nIn most cases you are behind a proxy or have bad network settings.\\n\\nIf you are behind a proxy, please make sure that the\\n'proxy' config is set properly.  See: 'npm help config'",
+      String(
+        This is a problem related to network connectivity.
+        In most cases you are behind a proxy or have bad network settings.
+        
+        If you are behind a proxy, please make sure that the
+        'proxy' config is set properly.  See: 'npm help config'
+      ),
     ],
   ],
   "summary": Array [
@@ -1226,7 +1471,10 @@ Object {
   "detail": Array [
     Array [
       "JSON.parse",
-      "Failed to parse JSON data.\\nNote: package.json must be actual JSON, not just JavaScript.",
+      String(
+        Failed to parse JSON data.
+        Note: package.json must be actual JSON, not just JavaScript.
+      ),
     ],
   ],
   "summary": Array [
@@ -1243,7 +1491,10 @@ Object {
   "detail": Array [
     Array [
       "JSON.parse",
-      "Failed to parse JSON data.\\nNote: package.json must be actual JSON, not just JavaScript.",
+      String(
+        Failed to parse JSON data.
+        Note: package.json must be actual JSON, not just JavaScript.
+      ),
     ],
   ],
   "summary": Array [
@@ -1260,7 +1511,13 @@ Object {
   "detail": Array [
     Array [
       "",
-      "Merge conflict detected in your package.json.\\n\\nPlease resolve the package.json conflict and retry the command:\\n\\n$ arg v",
+      String(
+        Merge conflict detected in your package.json.
+        
+        Please resolve the package.json conflict and retry the command:
+        
+        $ arg v
+      ),
     ],
   ],
   "summary": Array [],
diff --git a/tap-snapshots/test-lib-utils-explain-dep.js-TAP.test.js b/tap-snapshots/test/lib/utils/explain-dep.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-utils-explain-dep.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/explain-dep.js.test.cjs
diff --git a/tap-snapshots/test-lib-utils-explain-eresolve.js-TAP.test.js b/tap-snapshots/test/lib/utils/explain-eresolve.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-utils-explain-eresolve.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/explain-eresolve.js.test.cjs
diff --git a/tap-snapshots/test-lib-utils-npm-usage.js-TAP.test.js b/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-utils-npm-usage.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/npm-usage.js.test.cjs
diff --git a/tap-snapshots/test-lib-utils-open-url.js-TAP.test.js b/tap-snapshots/test/lib/utils/open-url.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-utils-open-url.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/open-url.js.test.cjs
diff --git a/tap-snapshots/test-lib-utils-reify-finish.js-TAP.test.js b/tap-snapshots/test/lib/utils/reify-finish.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-utils-reify-finish.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/reify-finish.js.test.cjs
diff --git a/tap-snapshots/test-lib-utils-reify-output.js-TAP.test.js b/tap-snapshots/test/lib/utils/reify-output.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-utils-reify-output.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/reify-output.js.test.cjs
diff --git a/tap-snapshots/test-lib-utils-tar.js-TAP.test.js b/tap-snapshots/test/lib/utils/tar.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-utils-tar.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/tar.js.test.cjs
diff --git a/tap-snapshots/test-lib-utils-update-notifier.js-TAP.test.js b/tap-snapshots/test/lib/utils/update-notifier.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-utils-update-notifier.js-TAP.test.js
rename to tap-snapshots/test/lib/utils/update-notifier.js.test.cjs
diff --git a/tap-snapshots/test-lib-view.js-TAP.test.js b/tap-snapshots/test/lib/view.js.test.cjs
similarity index 100%
rename from tap-snapshots/test-lib-view.js-TAP.test.js
rename to tap-snapshots/test/lib/view.js.test.cjs
diff --git a/test/bin/npm-cli.js b/test/bin/npm-cli.js
index bcca99c8c8fe1..7b4b619e2b771 100644
--- a/test/bin/npm-cli.js
+++ b/test/bin/npm-cli.js
@@ -1,7 +1,6 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 t.test('loading the bin calls the implementation', t => {
-  requireInject('../../bin/npm-cli.js', {
+  t.mock('../../bin/npm-cli.js', {
     '../../lib/cli.js': proc => {
       t.equal(proc, process, 'called implementation with process object')
       t.end()
diff --git a/test/bin/npx-cli.js b/test/bin/npx-cli.js
index 2b7b488297cab..5eeee30184363 100644
--- a/test/bin/npx-cli.js
+++ b/test/bin/npx-cli.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const npx = require.resolve('../../bin/npx-cli.js')
 const cli = require.resolve('../../lib/cli.js')
 const npm = require.resolve('../../bin/npm-cli.js')
@@ -7,42 +6,39 @@ const npm = require.resolve('../../bin/npm-cli.js')
 const logs = []
 console.error = (...msg) => logs.push(msg)
 
-t.afterEach(cb => {
-  logs.length = 0
-  cb()
-})
+t.afterEach(() => logs.length = 0)
 
 t.test('npx foo -> npm exec -- foo', t => {
   process.argv = ['node', npx, 'foo']
-  requireInject(npx, { [cli]: () => {} })
+  t.mock(npx, { [cli]: () => {} })
   t.strictSame(process.argv, ['node', npm, 'exec', '--', 'foo'])
   t.end()
 })
 
 t.test('npx -- foo -> npm exec -- foo', t => {
   process.argv = ['node', npx, '--', 'foo']
-  requireInject(npx, { [cli]: () => {} })
+  t.mock(npx, { [cli]: () => {} })
   t.strictSame(process.argv, ['node', npm, 'exec', '--', 'foo'])
   t.end()
 })
 
 t.test('npx -x y foo -z -> npm exec -x y -- foo -z', t => {
   process.argv = ['node', npx, '-x', 'y', 'foo', '-z']
-  requireInject(npx, { [cli]: () => {} })
+  t.mock(npx, { [cli]: () => {} })
   t.strictSame(process.argv, ['node', npm, 'exec', '-x', 'y', '--', 'foo', '-z'])
   t.end()
 })
 
 t.test('npx --x=y --no-install foo -z -> npm exec --x=y -- foo -z', t => {
   process.argv = ['node', npx, '--x=y', '--no-install', 'foo', '-z']
-  requireInject(npx, { [cli]: () => {} })
+  t.mock(npx, { [cli]: () => {} })
   t.strictSame(process.argv, ['node', npm, 'exec', '--x=y', '--yes=false', '--', 'foo', '-z'])
   t.end()
 })
 
 t.test('transform renamed options into proper values', t => {
   process.argv = ['node', npx, '-y', '--shell=bash', '-p', 'foo', '-c', 'asdf']
-  requireInject(npx, { [cli]: () => {} })
+  t.mock(npx, { [cli]: () => {} })
   t.strictSame(process.argv, ['node', npm, 'exec', '--yes', '--script-shell=bash', '--package', 'foo', '--call', 'asdf'])
   t.end()
 })
@@ -80,7 +76,7 @@ t.test('use a bunch of deprecated switches and options', t => {
     '--',
     'foobar',
   ]
-  requireInject(npx, { [cli]: () => {} })
+  t.mock(npx, { [cli]: () => {} })
   t.strictSame(process.argv, expect)
   t.strictSame(logs, [
     ['npx: the --npm argument has been removed.'],
diff --git a/test/lib/access.js b/test/lib/access.js
index a8e28c8eb9065..5fd170bab484a 100644
--- a/test/lib/access.js
+++ b/test/lib/access.js
@@ -1,5 +1,4 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 
 const Access = require('../../lib/access.js')
 
@@ -7,7 +6,7 @@ const npm = {
   output: () => null,
 }
 
-test('completion', t => {
+t.test('completion', t => {
   const access = new Access({ flatOptions: {} })
   const testComp = (argv, expect) => {
     const res = access.completion({conf: {argv: {remain: argv}}})
@@ -38,7 +37,7 @@ test('completion', t => {
   t.end()
 })
 
-test('subcommand required', t => {
+t.test('subcommand required', t => {
   const access = new Access({ flatOptions: {} })
   access.exec([], (err) => {
     t.match(err, access.usageError('Subcommand is required.'))
@@ -46,7 +45,7 @@ test('subcommand required', t => {
   })
 })
 
-test('unrecognized subcommand', (t) => {
+t.test('unrecognized subcommand', (t) => {
   const access = new Access({ flatOptions: {} })
   access.exec(['blerg'], (err) => {
     t.match(
@@ -58,7 +57,7 @@ test('unrecognized subcommand', (t) => {
   })
 })
 
-test('edit', (t) => {
+t.test('edit', (t) => {
   const access = new Access({ flatOptions: {} })
   access.exec([
     'edit',
@@ -73,7 +72,7 @@ test('edit', (t) => {
   })
 })
 
-test('access public on unscoped package', (t) => {
+t.test('access public on unscoped package', (t) => {
   const prefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'npm-access-public-pkg',
@@ -92,13 +91,13 @@ test('access public on unscoped package', (t) => {
   })
 })
 
-test('access public on scoped package', (t) => {
+t.test('access public on scoped package', (t) => {
   t.plan(4)
   const name = '@scoped/npm-access-public-pkg'
   const prefix = t.testdir({
     'package.json': JSON.stringify({ name }),
   })
-  const Access = requireInject('../../lib/access.js', {
+  const Access = t.mock('../../lib/access.js', {
     libnpmaccess: {
       public: (pkg, { registry }) => {
         t.equal(pkg, name, 'should use pkg name ref')
@@ -118,12 +117,12 @@ test('access public on scoped package', (t) => {
   access.exec([
     'public',
   ], (err) => {
-    t.ifError(err, 'npm access')
+    t.error(err, 'npm access')
     t.ok('should successfully access public on scoped package')
   })
 })
 
-test('access public on missing package.json', (t) => {
+t.test('access public on missing package.json', (t) => {
   const prefix = t.testdir({
     node_modules: {},
   })
@@ -140,7 +139,7 @@ test('access public on missing package.json', (t) => {
   })
 })
 
-test('access public on invalid package.json', (t) => {
+t.test('access public on invalid package.json', (t) => {
   const prefix = t.testdir({
     'package.json': '{\n',
     node_modules: {},
@@ -158,7 +157,7 @@ test('access public on invalid package.json', (t) => {
   })
 })
 
-test('access restricted on unscoped package', (t) => {
+t.test('access restricted on unscoped package', (t) => {
   const prefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'npm-access-restricted-pkg',
@@ -177,13 +176,13 @@ test('access restricted on unscoped package', (t) => {
   })
 })
 
-test('access restricted on scoped package', (t) => {
+t.test('access restricted on scoped package', (t) => {
   t.plan(4)
   const name = '@scoped/npm-access-restricted-pkg'
   const prefix = t.testdir({
     'package.json': JSON.stringify({ name }),
   })
-  const Access = requireInject('../../lib/access.js', {
+  const Access = t.mock('../../lib/access.js', {
     libnpmaccess: {
       restricted: (pkg, { registry }) => {
         t.equal(pkg, name, 'should use pkg name ref')
@@ -203,12 +202,12 @@ test('access restricted on scoped package', (t) => {
   access.exec([
     'restricted',
   ], (err) => {
-    t.ifError(err, 'npm access')
+    t.error(err, 'npm access')
     t.ok('should successfully access restricted on scoped package')
   })
 })
 
-test('access restricted on missing package.json', (t) => {
+t.test('access restricted on missing package.json', (t) => {
   const prefix = t.testdir({
     node_modules: {},
   })
@@ -225,7 +224,7 @@ test('access restricted on missing package.json', (t) => {
   })
 })
 
-test('access restricted on invalid package.json', (t) => {
+t.test('access restricted on invalid package.json', (t) => {
   const prefix = t.testdir({
     'package.json': '{\n',
     node_modules: {},
@@ -243,9 +242,9 @@ test('access restricted on invalid package.json', (t) => {
   })
 })
 
-test('access grant read-only', (t) => {
+t.test('access grant read-only', (t) => {
   t.plan(5)
-  const Access = requireInject('../../lib/access.js', {
+  const Access = t.mock('../../lib/access.js', {
     libnpmaccess: {
       grant: (spec, team, permissions) => {
         t.equal(spec, '@scoped/another', 'should use expected spec')
@@ -262,14 +261,14 @@ test('access grant read-only', (t) => {
     'myorg:myteam',
     '@scoped/another',
   ], (err) => {
-    t.ifError(err, 'npm access')
+    t.error(err, 'npm access')
     t.ok('should successfully access grant read-only')
   })
 })
 
-test('access grant read-write', (t) => {
+t.test('access grant read-write', (t) => {
   t.plan(5)
-  const Access = requireInject('../../lib/access.js', {
+  const Access = t.mock('../../lib/access.js', {
     libnpmaccess: {
       grant: (spec, team, permissions) => {
         t.equal(spec, '@scoped/another', 'should use expected spec')
@@ -286,19 +285,19 @@ test('access grant read-write', (t) => {
     'myorg:myteam',
     '@scoped/another',
   ], (err) => {
-    t.ifError(err, 'npm access')
+    t.error(err, 'npm access')
     t.ok('should successfully access grant read-write')
   })
 })
 
-test('access grant current cwd', (t) => {
+t.test('access grant current cwd', (t) => {
   t.plan(5)
   const prefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'yargs',
     }),
   })
-  const Access = requireInject('../../lib/access.js', {
+  const Access = t.mock('../../lib/access.js', {
     libnpmaccess: {
       grant: (spec, team, permissions) => {
         t.equal(spec, 'yargs', 'should use expected spec')
@@ -314,12 +313,12 @@ test('access grant current cwd', (t) => {
     'read-write',
     'myorg:myteam',
   ], (err) => {
-    t.ifError(err, 'npm access')
+    t.error(err, 'npm access')
     t.ok('should successfully access grant current cwd')
   })
 })
 
-test('access grant others', (t) => {
+t.test('access grant others', (t) => {
   const access = new Access({ flatOptions: {} })
   access.exec([
     'grant',
@@ -336,7 +335,7 @@ test('access grant others', (t) => {
   })
 })
 
-test('access grant missing team args', (t) => {
+t.test('access grant missing team args', (t) => {
   const access = new Access({ flatOptions: {} })
   access.exec([
     'grant',
@@ -353,7 +352,7 @@ test('access grant missing team args', (t) => {
   })
 })
 
-test('access grant malformed team arg', (t) => {
+t.test('access grant malformed team arg', (t) => {
   const access = new Access({ flatOptions: {} })
   access.exec([
     'grant',
@@ -370,9 +369,9 @@ test('access grant malformed team arg', (t) => {
   })
 })
 
-test('access 2fa-required/2fa-not-required', t => {
+t.test('access 2fa-required/2fa-not-required', t => {
   t.plan(2)
-  const Access = requireInject('../../lib/access.js', {
+  const Access = t.mock('../../lib/access.js', {
     libnpmaccess: {
       tfaRequired: (spec) => {
         t.equal(spec, '@scope/pkg', 'should use expected spec')
@@ -397,9 +396,9 @@ test('access 2fa-required/2fa-not-required', t => {
   })
 })
 
-test('access revoke', (t) => {
+t.test('access revoke', (t) => {
   t.plan(4)
-  const Access = requireInject('../../lib/access.js', {
+  const Access = t.mock('../../lib/access.js', {
     libnpmaccess: {
       revoke: (spec, team) => {
         t.equal(spec, '@scoped/another', 'should use expected spec')
@@ -414,12 +413,12 @@ test('access revoke', (t) => {
     'myorg:myteam',
     '@scoped/another',
   ], (err) => {
-    t.ifError(err, 'npm access')
+    t.error(err, 'npm access')
     t.ok('should successfully access revoke')
   })
 })
 
-test('access revoke missing team args', (t) => {
+t.test('access revoke missing team args', (t) => {
   const access = new Access({ flatOptions: {} })
   access.exec([
     'revoke',
@@ -435,7 +434,7 @@ test('access revoke missing team args', (t) => {
   })
 })
 
-test('access revoke malformed team arg', (t) => {
+t.test('access revoke malformed team arg', (t) => {
   const access = new Access({ flatOptions: {} })
   access.exec([
     'revoke',
@@ -451,9 +450,9 @@ test('access revoke malformed team arg', (t) => {
   })
 })
 
-test('npm access ls-packages with no team', (t) => {
+t.test('npm access ls-packages with no team', (t) => {
   t.plan(3)
-  const Access = requireInject('../../lib/access.js', {
+  const Access = t.mock('../../lib/access.js', {
     libnpmaccess: {
       lsPackages: (entity) => {
         t.equal(entity, 'foo', 'should use expected entity')
@@ -466,14 +465,14 @@ test('npm access ls-packages with no team', (t) => {
   access.exec([
     'ls-packages',
   ], (err) => {
-    t.ifError(err, 'npm access')
+    t.error(err, 'npm access')
     t.ok('should successfully access ls-packages with no team')
   })
 })
 
-test('access ls-packages on team', (t) => {
+t.test('access ls-packages on team', (t) => {
   t.plan(3)
-  const Access = requireInject('../../lib/access.js', {
+  const Access = t.mock('../../lib/access.js', {
     libnpmaccess: {
       lsPackages: (entity) => {
         t.equal(entity, 'myorg:myteam', 'should use expected entity')
@@ -486,19 +485,19 @@ test('access ls-packages on team', (t) => {
     'ls-packages',
     'myorg:myteam',
   ], (err) => {
-    t.ifError(err, 'npm access')
+    t.error(err, 'npm access')
     t.ok('should successfully access ls-packages on team')
   })
 })
 
-test('access ls-collaborators on current', (t) => {
+t.test('access ls-collaborators on current', (t) => {
   t.plan(3)
   const prefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'yargs',
     }),
   })
-  const Access = requireInject('../../lib/access.js', {
+  const Access = t.mock('../../lib/access.js', {
     libnpmaccess: {
       lsCollaborators: (spec) => {
         t.equal(spec, 'yargs', 'should use expected spec')
@@ -510,14 +509,14 @@ test('access ls-collaborators on current', (t) => {
   access.exec([
     'ls-collaborators',
   ], (err) => {
-    t.ifError(err, 'npm access')
+    t.error(err, 'npm access')
     t.ok('should successfully access ls-collaborators on current')
   })
 })
 
-test('access ls-collaborators on spec', (t) => {
+t.test('access ls-collaborators on spec', (t) => {
   t.plan(3)
-  const Access = requireInject('../../lib/access.js', {
+  const Access = t.mock('../../lib/access.js', {
     libnpmaccess: {
       lsCollaborators: (spec) => {
         t.equal(spec, 'yargs', 'should use expected spec')
@@ -530,7 +529,7 @@ test('access ls-collaborators on spec', (t) => {
     'ls-collaborators',
     'yargs',
   ], (err) => {
-    t.ifError(err, 'npm access')
+    t.error(err, 'npm access')
     t.ok('should successfully access ls-packages with no team')
   })
 })
diff --git a/test/lib/adduser.js b/test/lib/adduser.js
index d9106e1bda8e5..5ce61e12755dc 100644
--- a/test/lib/adduser.js
+++ b/test/lib/adduser.js
@@ -1,5 +1,4 @@
-const requireInject = require('require-inject')
-const { test } = require('tap')
+const t = require('tap')
 const { getCredentialsByURI, setCredentialsByURI } =
   require('@npmcli/config').prototype
 
@@ -66,7 +65,7 @@ const npm = {
   },
 }
 
-const AddUser = requireInject('../../lib/adduser.js', {
+const AddUser = t.mock('../../lib/adduser.js', {
   npmlog: {
     disableProgress: () => null,
     notice: (_, msg) => {
@@ -78,13 +77,13 @@ const AddUser = requireInject('../../lib/adduser.js', {
 
 const adduser = new AddUser(npm)
 
-test('usage', (t) => {
+t.test('usage', (t) => {
   t.match(adduser.usage, 'adduser', 'usage has command name in it')
   t.end()
 })
-test('simple login', (t) => {
+t.test('simple login', (t) => {
   adduser.exec([], (err) => {
-    t.ifError(err, 'npm adduser')
+    t.error(err, 'npm adduser')
 
     t.equal(
       registryOutput,
@@ -92,7 +91,7 @@ test('simple login', (t) => {
       'should have correct message result'
     )
 
-    t.deepEqual(
+    t.same(
       deletedConfig,
       {
         _token: 'user',
@@ -108,7 +107,7 @@ test('simple login', (t) => {
       'should delete token in user config'
     )
 
-    t.deepEqual(
+    t.same(
       setConfig,
       {
         '//registry.npmjs.org/:_password': { value: 'cA==', where: 'user' },
@@ -133,7 +132,7 @@ test('simple login', (t) => {
   })
 })
 
-test('bad auth type', (t) => {
+t.test('bad auth type', (t) => {
   _flatOptions.authType = 'foo'
 
   adduser.exec([], (err) => {
@@ -151,13 +150,13 @@ test('bad auth type', (t) => {
   })
 })
 
-test('scoped login', (t) => {
+t.test('scoped login', (t) => {
   _flatOptions.scope = '@myscope'
 
   adduser.exec([], (err) => {
-    t.ifError(err, 'npm adduser')
+    t.error(err, 'npm adduser')
 
-    t.deepEqual(
+    t.same(
       setConfig['@myscope:registry'],
       { value: 'https://registry.npmjs.org/', where: 'user' },
       'should set scoped registry config'
@@ -171,14 +170,14 @@ test('scoped login', (t) => {
   })
 })
 
-test('scoped login with valid scoped registry config', (t) => {
+t.test('scoped login with valid scoped registry config', (t) => {
   _flatOptions['@myscope:registry'] = 'https://diff-registry.npmjs.com/'
   _flatOptions.scope = '@myscope'
 
   adduser.exec([], (err) => {
-    t.ifError(err, 'npm adduser')
+    t.error(err, 'npm adduser')
 
-    t.deepEqual(
+    t.same(
       setConfig['@myscope:registry'],
       { value: 'https://diff-registry.npmjs.com/', where: 'user' },
       'should keep scoped registry config'
@@ -193,7 +192,7 @@ test('scoped login with valid scoped registry config', (t) => {
   })
 })
 
-test('save config failure', (t) => {
+t.test('save config failure', (t) => {
   failSave = true
 
   adduser.exec([], (err) => {
diff --git a/test/lib/audit.js b/test/lib/audit.js
index a25e6b0e27740..bb6f06debc51f 100644
--- a/test/lib/audit.js
+++ b/test/lib/audit.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 
 t.test('should audit using Arborist', t => {
@@ -19,7 +18,7 @@ t.test('should audit using Arborist', t => {
       OUTPUT_CALLED = true
     },
   })
-  const Audit = requireInject('../../lib/audit.js', {
+  const Audit = t.mock('../../lib/audit.js', {
     'npm-audit-report': () => {
       AUDIT_REPORT_CALLED = true
       return {
@@ -74,7 +73,7 @@ t.test('should audit - json', t => {
     output: () => {},
   })
 
-  const Audit = requireInject('../../lib/audit.js', {
+  const Audit = t.mock('../../lib/audit.js', {
     'npm-audit-report': () => ({
       report: 'there are vulnerabilities',
       exitCode: 0,
@@ -115,7 +114,7 @@ t.test('report endpoint error', t => {
           OUTPUT.push(msg)
         },
       })
-      const Audit = requireInject('../../lib/audit.js', {
+      const Audit = t.mock('../../lib/audit.js', {
         'npm-audit-report': () => {
           throw new Error('should not call audit report when there are errors')
         },
diff --git a/test/lib/auth/legacy.js b/test/lib/auth/legacy.js
index f5297c58179c6..d06f9535742fb 100644
--- a/test/lib/auth/legacy.js
+++ b/test/lib/auth/legacy.js
@@ -1,12 +1,11 @@
-const requireInject = require('require-inject')
-const { test } = require('tap')
+const t = require('tap')
 
 let log = ''
 
 const token = '24528a24f240'
 const profile = {}
 const read = {}
-const legacy = requireInject('../../../lib/auth/legacy.js', {
+const legacy = t.mock('../../../lib/auth/legacy.js', {
   npmlog: {
     info: (...msgs) => {
       log += msgs.join(' ')
@@ -26,7 +25,7 @@ const npm = {
   },
 }
 
-test('login using username/password with token result', async (t) => {
+t.test('login using username/password with token result', async (t) => {
   profile.login = () => {
     return { token }
   }
@@ -57,7 +56,7 @@ test('login using username/password with token result', async (t) => {
     'should have correct message result'
   )
 
-  t.deepEqual(
+  t.same(
     newCreds,
     { token },
     'should return expected obj from profile.login'
@@ -67,7 +66,7 @@ test('login using username/password with token result', async (t) => {
   delete profile.login
 })
 
-test('login using username/password with user info result', async (t) => {
+t.test('login using username/password with user info result', async (t) => {
   profile.login = () => {
     return null
   }
@@ -92,7 +91,7 @@ test('login using username/password with user info result', async (t) => {
     'should have correct message result'
   )
 
-  t.deepEqual(
+  t.same(
     newCreds,
     {
       username: 'u',
@@ -107,7 +106,7 @@ test('login using username/password with user info result', async (t) => {
   delete profile.login
 })
 
-test('login otp requested', async (t) => {
+t.test('login otp requested', async (t) => {
   t.plan(5)
 
   profile.login = () => Promise.reject(Object.assign(
@@ -143,7 +142,7 @@ test('login otp requested', async (t) => {
     'should have correct message result'
   )
 
-  t.deepEqual(
+  t.same(
     newCreds,
     { token },
     'should return token from loginCouch result'
@@ -155,7 +154,7 @@ test('login otp requested', async (t) => {
   delete read.otp
 })
 
-test('login missing basic credential info', async (t) => {
+t.test('login missing basic credential info', async (t) => {
   profile.login = () => Promise.reject(Object.assign(
     new Error('missing info'),
     { code: 'ERROR' }
@@ -178,7 +177,7 @@ test('login missing basic credential info', async (t) => {
   delete profile.login
 })
 
-test('create new user when user not found', async (t) => {
+t.test('create new user when user not found', async (t) => {
   t.plan(6)
 
   profile.login = () => Promise.reject(Object.assign(
@@ -219,7 +218,7 @@ test('create new user when user not found', async (t) => {
     'should have correct message result'
   )
 
-  t.deepEqual(
+  t.same(
     newCreds,
     { token },
     'should return expected obj from profile.login'
@@ -230,7 +229,7 @@ test('create new user when user not found', async (t) => {
   delete profile.login
 })
 
-test('prompts for user info if required', async (t) => {
+t.test('prompts for user info if required', async (t) => {
   t.plan(4)
 
   profile.login = async (opener, prompt, opts) => {
@@ -266,7 +265,7 @@ test('prompts for user info if required', async (t) => {
     'should have correct message result'
   )
 
-  t.deepEqual(
+  t.same(
     newCreds,
     {
       username: 'foo',
@@ -284,7 +283,7 @@ test('prompts for user info if required', async (t) => {
   delete read.email
 })
 
-test('request otp when creating new user', async (t) => {
+t.test('request otp when creating new user', async (t) => {
   t.plan(3)
 
   profile.login = () => Promise.reject(Object.assign(
@@ -322,7 +321,7 @@ test('request otp when creating new user', async (t) => {
   delete read.otp
 })
 
-test('unknown error during user creation', async (t) => {
+t.test('unknown error during user creation', async (t) => {
   profile.login = () => Promise.reject(Object.assign(
     new Error('missing info'),
     { code: 'ERROR' }
@@ -352,7 +351,7 @@ test('unknown error during user creation', async (t) => {
   delete profile.login
 })
 
-test('open url error', async (t) => {
+t.test('open url error', async (t) => {
   profile.login = async (opener, prompt, opts) => {
     await opener()
   }
@@ -374,7 +373,7 @@ test('open url error', async (t) => {
   delete profile.login
 })
 
-test('login no credentials provided', async (t) => {
+t.test('login no credentials provided', async (t) => {
   profile.login = () => ({ token })
 
   await legacy(npm, {
@@ -398,7 +397,7 @@ test('login no credentials provided', async (t) => {
   delete profile.login
 })
 
-test('scoped login', async (t) => {
+t.test('scoped login', async (t) => {
   profile.login = () => ({ token })
 
   const { message } = await legacy(npm, {
diff --git a/test/lib/auth/oauth.js b/test/lib/auth/oauth.js
index c2f4c3443a234..0c317fb9a130e 100644
--- a/test/lib/auth/oauth.js
+++ b/test/lib/auth/oauth.js
@@ -1,7 +1,6 @@
-const requireInject = require('require-inject')
-const { test } = require('tap')
+const t = require('tap')
 
-test('oauth login', (t) => {
+t.test('oauth login', (t) => {
   t.plan(3)
   const oauthOpts = {
     creds: {},
@@ -17,7 +16,7 @@ test('oauth login', (t) => {
       },
     },
   }
-  const oauth = requireInject('../../../lib/auth/oauth.js', {
+  const oauth = t.mock('../../../lib/auth/oauth.js', {
     '../../../lib/auth/sso.js': (npm, opts) => {
       t.equal(opts, oauthOpts, 'should forward opts')
     },
diff --git a/test/lib/auth/saml.js b/test/lib/auth/saml.js
index b8c21f649edc0..1558e0db8eb29 100644
--- a/test/lib/auth/saml.js
+++ b/test/lib/auth/saml.js
@@ -1,7 +1,6 @@
-const requireInject = require('require-inject')
-const { test } = require('tap')
+const t = require('tap')
 
-test('saml login', (t) => {
+t.test('saml login', (t) => {
   t.plan(3)
   const samlOpts = {
     creds: {},
@@ -17,7 +16,7 @@ test('saml login', (t) => {
       },
     },
   }
-  const saml = requireInject('../../../lib/auth/saml.js', {
+  const saml = t.mock('../../../lib/auth/saml.js', {
     '../../../lib/auth/sso.js': (npm, opts) => {
       t.equal(opts, samlOpts, 'should forward opts')
     },
diff --git a/test/lib/auth/sso.js b/test/lib/auth/sso.js
index 6f3d981a6fff7..11be002aee345 100644
--- a/test/lib/auth/sso.js
+++ b/test/lib/auth/sso.js
@@ -1,5 +1,4 @@
-const requireInject = require('require-inject')
-const { test } = require('tap')
+const t = require('tap')
 
 let log = ''
 let warn = ''
@@ -11,7 +10,7 @@ const token = '24528a24f240'
 const SSO_URL = 'https://registry.npmjs.org/{SSO_URL}'
 const profile = {}
 const npmFetch = {}
-const sso = requireInject('../../../lib/auth/sso.js', {
+const sso = t.mock('../../../lib/auth/sso.js', {
   npmlog: {
     info: (...msgs) => {
       log += msgs.join(' ') + '\n'
@@ -46,7 +45,7 @@ const npm = {
   flatOptions: _flatOptions,
 }
 
-test('empty login', async (t) => {
+t.test('empty login', async (t) => {
   _flatOptions.ssoType = false
 
   await t.rejects(
@@ -66,13 +65,13 @@ test('empty login', async (t) => {
   warn = ''
 })
 
-test('simple login', async (t) => {
+t.test('simple login', async (t) => {
   t.plan(6)
 
   profile.loginCouch = (username, password, opts) => {
     t.equal(username, 'npm_oauth_auth_dummy_user', 'should use dummy user')
     t.equal(password, 'placeholder', 'should use dummy password')
-    t.deepEqual(
+    t.same(
       opts,
       {
         creds: {},
@@ -109,7 +108,7 @@ test('simple login', async (t) => {
     'should have correct logged info msg'
   )
 
-  t.deepEqual(
+  t.same(
     newCreds,
     { token },
     'should return expected resulting credentials'
@@ -121,7 +120,7 @@ test('simple login', async (t) => {
   delete npmFetch.json
 })
 
-test('polling retry', async (t) => {
+t.test('polling retry', async (t) => {
   t.plan(3)
 
   profile.loginCouch = () => ({ token, sso: SSO_URL })
@@ -168,7 +167,7 @@ test('polling retry', async (t) => {
   delete npmFetch.json
 })
 
-test('polling error', async (t) => {
+t.test('polling error', async (t) => {
   profile.loginCouch = () => ({ token, sso: SSO_URL })
   npmFetch.json = () => Promise.reject(Object.assign(
     new Error('unknown error'),
@@ -191,7 +190,7 @@ test('polling error', async (t) => {
   delete npmFetch.json
 })
 
-test('no token retrieved from loginCouch', async (t) => {
+t.test('no token retrieved from loginCouch', async (t) => {
   profile.loginCouch = () => ({})
 
   await t.rejects(
@@ -209,7 +208,7 @@ test('no token retrieved from loginCouch', async (t) => {
   delete profile.loginCouch
 })
 
-test('no sso url retrieved from loginCouch', async (t) => {
+t.test('no sso url retrieved from loginCouch', async (t) => {
   profile.loginCouch = () => Promise.resolve({ token })
 
   await t.rejects(
@@ -227,7 +226,7 @@ test('no sso url retrieved from loginCouch', async (t) => {
   delete profile.loginCouch
 })
 
-test('scoped login', async (t) => {
+t.test('scoped login', async (t) => {
   profile.loginCouch = () => ({ token, sso: SSO_URL })
   npmFetch.json = () => Promise.resolve({ username: 'foo' })
 
@@ -252,7 +251,7 @@ test('scoped login', async (t) => {
     'should have correct logged info msg'
   )
 
-  t.deepEqual(
+  t.same(
     newCreds,
     { token },
     'should return expected resulting credentials'
diff --git a/test/lib/bin.js b/test/lib/bin.js
index 1d9341169be15..898e7ba439b88 100644
--- a/test/lib/bin.js
+++ b/test/lib/bin.js
@@ -1,8 +1,7 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 const mockNpm = require('../fixtures/mock-npm')
 
-test('bin', (t) => {
+t.test('bin', (t) => {
   t.plan(4)
   const dir = '/bin/dir'
 
@@ -19,15 +18,15 @@ test('bin', (t) => {
   t.match(bin.usage, 'bin', 'usage has command name in it')
 
   bin.exec([], (err) => {
-    t.ifError(err, 'npm bin')
+    t.error(err, 'npm bin')
     t.ok('should have printed directory')
   })
 })
 
-test('bin -g', (t) => {
+t.test('bin -g', (t) => {
   t.plan(3)
   const consoleError = console.error
-  t.tearDown(() => {
+  t.teardown(() => {
     console.error = consoleError
   })
 
@@ -36,7 +35,7 @@ test('bin -g', (t) => {
   }
   const dir = '/bin/dir'
 
-  const Bin = requireInject('../../lib/bin.js', {
+  const Bin = t.mock('../../lib/bin.js', {
     '../../lib/utils/path.js': [dir],
   })
 
@@ -50,15 +49,15 @@ test('bin -g', (t) => {
   const bin = new Bin(npm)
 
   bin.exec([], (err) => {
-    t.ifError(err, 'npm bin')
+    t.error(err, 'npm bin')
     t.ok('should have printed directory')
   })
 })
 
-test('bin -g (not in path)', (t) => {
+t.test('bin -g (not in path)', (t) => {
   t.plan(4)
   const consoleError = console.error
-  t.tearDown(() => {
+  t.teardown(() => {
     console.error = consoleError
   })
 
@@ -67,7 +66,7 @@ test('bin -g (not in path)', (t) => {
   }
   const dir = '/bin/dir'
 
-  const Bin = requireInject('../../lib/bin.js', {
+  const Bin = t.mock('../../lib/bin.js', {
     '../../lib/utils/path.js': ['/not/my/dir'],
   })
   const npm = mockNpm({
@@ -80,7 +79,7 @@ test('bin -g (not in path)', (t) => {
   const bin = new Bin(npm)
 
   bin.exec([], (err) => {
-    t.ifError(err, 'npm bin')
+    t.error(err, 'npm bin')
     t.ok('should have printed directory')
   })
 })
diff --git a/test/lib/bugs.js b/test/lib/bugs.js
index 21b1a98411ec6..1cc6e06eee650 100644
--- a/test/lib/bugs.js
+++ b/test/lib/bugs.js
@@ -1,6 +1,5 @@
 const t = require('tap')
 
-const requireInject = require('require-inject')
 const pacote = {
   manifest: async (spec, options) => {
     return spec === 'nobugs' ? {
@@ -48,7 +47,7 @@ const openUrl = async (npm, url, errMsg) => {
   opened[url]++
 }
 
-const Bugs = requireInject('../../lib/bugs.js', {
+const Bugs = t.mock('../../lib/bugs.js', {
   pacote,
   '../../lib/utils/open-url.js': openUrl,
 })
diff --git a/test/lib/cache.js b/test/lib/cache.js
index 0fdf768568479..bbebae8894bab 100644
--- a/test/lib/cache.js
+++ b/test/lib/cache.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 const path = require('path')
 
@@ -47,7 +46,7 @@ const cacache = {
   },
 }
 
-const Cache = requireInject('../../lib/cache.js', {
+const Cache = t.mock('../../lib/cache.js', {
   cacache,
   npmlog,
   pacote,
@@ -89,7 +88,7 @@ t.test('cache clean (force)', t => {
   })
 
   cache.exec(['clear'], err => {
-    t.ifError(err)
+    t.error(err)
     t.equal(rimrafPath, path.join(npm.cache, '_cacache'))
     t.end()
   })
@@ -124,7 +123,7 @@ t.test('cache add pkg only', t => {
   })
 
   cache.exec(['add', 'mypkg'], err => {
-    t.ifError(err)
+    t.error(err)
     t.strictSame(logOutput, [
       ['silly', 'cache add', 'args', ['mypkg']],
       ['silly', 'cache add', 'spec', 'mypkg'],
@@ -143,7 +142,7 @@ t.test('cache add pkg w/ spec modifier', t => {
   })
 
   cache.exec(['add', 'mypkg', 'latest'], err => {
-    t.ifError(err)
+    t.error(err)
     t.strictSame(logOutput, [
       ['silly', 'cache add', 'args', ['mypkg', 'latest']],
       ['silly', 'cache add', 'spec', 'mypkg@latest'],
@@ -160,7 +159,7 @@ t.test('cache verify', t => {
   })
 
   cache.exec(['verify'], err => {
-    t.ifError(err)
+    t.error(err)
     t.match(outputOutput, [
       `Cache verified and compressed (${path.join(npm.cache, '_cacache')})`,
       'Content verified: 1 (100 bytes)',
@@ -187,7 +186,7 @@ t.test('cache verify w/ extra output', t => {
   })
 
   cache.exec(['check'], err => {
-    t.ifError(err)
+    t.error(err)
     t.match(outputOutput, [
       `Cache verified and compressed (~${path.join('/fake/path', '_cacache')})`,
       'Content verified: 1 (100 bytes)',
diff --git a/test/lib/ci.js b/test/lib/ci.js
index 7f06a6cebcbc1..b60375c289842 100644
--- a/test/lib/ci.js
+++ b/test/lib/ci.js
@@ -2,15 +2,14 @@ const fs = require('fs')
 const util = require('util')
 const readdir = util.promisify(fs.readdir)
 
-const { test } = require('tap')
+const t = require('tap')
 
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 
-test('should ignore scripts with --ignore-scripts', (t) => {
+t.test('should ignore scripts with --ignore-scripts', (t) => {
   const SCRIPTS = []
   let REIFY_CALLED = false
-  const CI = requireInject('../../lib/ci.js', {
+  const CI = t.mock('../../lib/ci.js', {
     '../../lib/utils/reify-finish.js': async () => {},
     '@npmcli/run-script': ({ event }) => {
       SCRIPTS.push(event)
@@ -42,7 +41,7 @@ test('should ignore scripts with --ignore-scripts', (t) => {
   })
 })
 
-test('should use Arborist and run-script', (t) => {
+t.test('should use Arborist and run-script', (t) => {
   const scripts = [
     'preinstall',
     'install',
@@ -88,7 +87,7 @@ test('should use Arborist and run-script', (t) => {
   const expectRimrafs = 3
   let actualRimrafs = 0
 
-  const CI = requireInject('../../lib/ci.js', {
+  const CI = t.mock('../../lib/ci.js', {
     '../../lib/utils/reify-finish.js': async () => {},
     '@npmcli/run-script': opts => {
       t.match(opts, { event: scripts.shift() })
@@ -134,8 +133,8 @@ test('should use Arborist and run-script', (t) => {
   })
 })
 
-test('should pass flatOptions to Arborist.reify', (t) => {
-  const CI = requireInject('../../lib/ci.js', {
+t.test('should pass flatOptions to Arborist.reify', (t) => {
+  const CI = t.mock('../../lib/ci.js', {
     '../../lib/utils/reify-finish.js': async () => {},
     '@npmcli/run-script': opts => {},
     '@npmcli/arborist': function () {
@@ -159,13 +158,13 @@ test('should pass flatOptions to Arborist.reify', (t) => {
   })
 })
 
-test('should throw if package-lock.json or npm-shrinkwrap missing', (t) => {
+t.test('should throw if package-lock.json or npm-shrinkwrap missing', (t) => {
   const testDir = t.testdir({
     'index.js': 'some contents',
     'package.json': 'some info',
   })
 
-  const CI = requireInject('../../lib/ci.js', {
+  const CI = t.mock('../../lib/ci.js', {
     '@npmcli/run-script': opts => {},
     '../../lib/utils/reify-finish.js': async () => {},
     npmlog: {
@@ -188,8 +187,8 @@ test('should throw if package-lock.json or npm-shrinkwrap missing', (t) => {
   })
 })
 
-test('should throw ECIGLOBAL', (t) => {
-  const CI = requireInject('../../lib/ci.js', {
+t.test('should throw ECIGLOBAL', (t) => {
+  const CI = t.mock('../../lib/ci.js', {
     '@npmcli/run-script': opts => {},
     '../../lib/utils/reify-finish.js': async () => {},
   })
@@ -201,20 +200,20 @@ test('should throw ECIGLOBAL', (t) => {
   })
   const ci = new CI(npm)
   ci.exec(null, (err, res) => {
-    t.equals(err.code, 'ECIGLOBAL', 'throws error with global packages')
+    t.equal(err.code, 'ECIGLOBAL', 'throws error with global packages')
     t.notOk(res)
     t.end()
   })
 })
 
-test('should remove existing node_modules before installing', (t) => {
+t.test('should remove existing node_modules before installing', (t) => {
   const testDir = t.testdir({
     node_modules: {
       'some-file': 'some contents',
     },
   })
 
-  const CI = requireInject('../../lib/ci.js', {
+  const CI = t.mock('../../lib/ci.js', {
     '@npmcli/run-script': opts => {},
     '../../lib/utils/reify-finish.js': async () => {},
     '@npmcli/arborist': function () {
diff --git a/test/lib/cli.js b/test/lib/cli.js
index 28e44394e16dc..f491c6174b85e 100644
--- a/test/lib/cli.js
+++ b/test/lib/cli.js
@@ -43,8 +43,7 @@ const npmlogMock = {
   info: (...msg) => logs.push(['info', ...msg]),
 }
 
-const requireInject = require('require-inject')
-const cli = requireInject.installGlobally('../../lib/cli.js', {
+const cli = t.mock('../../lib/cli.js', {
   '../../lib/npm.js': npmock,
   '../../lib/utils/did-you-mean.js': () => '\ntest did you mean',
   '../../lib/utils/unsupported.js': unsupportedMock,
diff --git a/test/lib/completion.js b/test/lib/completion.js
index c6ef901a7ed7d..4f7d4a5fd6e38 100644
--- a/test/lib/completion.js
+++ b/test/lib/completion.js
@@ -1,5 +1,4 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 const fs = require('fs')
 const path = require('path')
 
@@ -81,7 +80,7 @@ const deref = (cmd) => {
   return cmd
 }
 
-const Completion = requireInject('../../lib/completion.js', {
+const Completion = t.mock('../../lib/completion.js', {
   '../../lib/utils/cmd-list.js': cmdList,
   '../../lib/utils/config/index.js': config,
   '../../lib/utils/deref-command.js': deref,
@@ -89,7 +88,7 @@ const Completion = requireInject('../../lib/completion.js', {
 })
 const completion = new Completion(npm)
 
-test('completion completion', async t => {
+t.test('completion completion', async t => {
   const home = process.env.HOME
   t.teardown(() => {
     process.env.HOME = home
@@ -108,7 +107,7 @@ test('completion completion', async t => {
   t.end()
 })
 
-test('completion completion no known shells', async t => {
+t.test('completion completion no known shells', async t => {
   const home = process.env.HOME
   t.teardown(() => {
     process.env.HOME = home
@@ -121,14 +120,14 @@ test('completion completion no known shells', async t => {
   t.end()
 })
 
-test('completion completion wrong word count', async t => {
+t.test('completion completion wrong word count', async t => {
   const res = await completion.completion({ w: 3 })
   t.strictSame(res, undefined, 'no responses')
   t.end()
 })
 
-test('completion errors in windows without bash', t => {
-  const Compl = requireInject('../../lib/completion.js', {
+t.test('completion errors in windows without bash', t => {
+  const Compl = t.mock('../../lib/completion.js', {
     '../../lib/utils/is-windows-shell.js': true,
   })
 
@@ -143,7 +142,7 @@ test('completion errors in windows without bash', t => {
   })
 })
 
-test('dump script when completion is not being attempted', t => {
+t.test('dump script when completion is not being attempted', t => {
   const _write = process.stdout.write
   const _on = process.stdout.on
   t.teardown(() => {
@@ -176,7 +175,7 @@ test('dump script when completion is not being attempted', t => {
   })
 })
 
-test('dump script exits correctly when EPIPE is emitted on stdout', t => {
+t.test('dump script exits correctly when EPIPE is emitted on stdout', t => {
   const _write = process.stdout.write
   const _on = process.stdout.on
   t.teardown(() => {
@@ -209,7 +208,7 @@ test('dump script exits correctly when EPIPE is emitted on stdout', t => {
   })
 })
 
-test('non EPIPE errors cause failures', t => {
+t.test('non EPIPE errors cause failures', t => {
   const _write = process.stdout.write
   const _on = process.stdout.on
   t.teardown(() => {
@@ -240,7 +239,7 @@ test('non EPIPE errors cause failures', t => {
   })
 })
 
-test('completion completes single command name', t => {
+t.test('completion completes single command name', t => {
   process.env.COMP_CWORD = 1
   process.env.COMP_LINE = 'npm c'
   process.env.COMP_POINT = process.env.COMP_LINE.length
@@ -262,7 +261,7 @@ test('completion completes single command name', t => {
   })
 })
 
-test('completion completes command names', t => {
+t.test('completion completes command names', t => {
   process.env.COMP_CWORD = 1
   process.env.COMP_LINE = 'npm a'
   process.env.COMP_POINT = process.env.COMP_LINE.length
@@ -284,7 +283,7 @@ test('completion completes command names', t => {
   })
 })
 
-test('completion of invalid command name does nothing', t => {
+t.test('completion of invalid command name does nothing', t => {
   process.env.COMP_CWORD = 1
   process.env.COMP_LINE = 'npm compute'
   process.env.COMP_POINT = process.env.COMP_LINE.length
@@ -306,7 +305,7 @@ test('completion of invalid command name does nothing', t => {
   })
 })
 
-test('handles async completion function', t => {
+t.test('handles async completion function', t => {
   process.env.COMP_CWORD = 2
   process.env.COMP_LINE = 'npm promise'
   process.env.COMP_POINT = process.env.COMP_LINE.length
@@ -335,7 +334,7 @@ test('handles async completion function', t => {
   })
 })
 
-test('completion triggers command completions', t => {
+t.test('completion triggers command completions', t => {
   process.env.COMP_CWORD = 2
   process.env.COMP_LINE = 'npm access '
   process.env.COMP_POINT = process.env.COMP_LINE.length
@@ -364,7 +363,7 @@ test('completion triggers command completions', t => {
   })
 })
 
-test('completion triggers filtered command completions', t => {
+t.test('completion triggers filtered command completions', t => {
   process.env.COMP_CWORD = 2
   process.env.COMP_LINE = 'npm access p'
   process.env.COMP_POINT = process.env.COMP_LINE.length
@@ -393,7 +392,7 @@ test('completion triggers filtered command completions', t => {
   })
 })
 
-test('completions for commands that return nested arrays are joined', t => {
+t.test('completions for commands that return nested arrays are joined', t => {
   process.env.COMP_CWORD = 2
   process.env.COMP_LINE = 'npm completion '
   process.env.COMP_POINT = process.env.COMP_LINE.length
@@ -422,7 +421,7 @@ test('completions for commands that return nested arrays are joined', t => {
   })
 })
 
-test('completions for commands that return nothing work correctly', t => {
+t.test('completions for commands that return nothing work correctly', t => {
   process.env.COMP_CWORD = 2
   process.env.COMP_LINE = 'npm donothing '
   process.env.COMP_POINT = process.env.COMP_LINE.length
@@ -451,7 +450,7 @@ test('completions for commands that return nothing work correctly', t => {
   })
 })
 
-test('completions for commands that return a single item work correctly', t => {
+t.test('completions for commands that return a single item work correctly', t => {
   process.env.COMP_CWORD = 2
   process.env.COMP_LINE = 'npm driveaboat '
   process.env.COMP_POINT = process.env.COMP_LINE.length
@@ -480,7 +479,7 @@ test('completions for commands that return a single item work correctly', t => {
   })
 })
 
-test('command completion for commands with no completion return no results', t => {
+t.test('command completion for commands with no completion return no results', t => {
   process.env.COMP_CWORD = 2
   process.env.COMP_LINE = 'npm adduser '
   process.env.COMP_POINT = process.env.COMP_LINE.length
@@ -510,7 +509,7 @@ test('command completion for commands with no completion return no results', t =
   })
 })
 
-test('command completion errors propagate', t => {
+t.test('command completion errors propagate', t => {
   process.env.COMP_CWORD = 2
   process.env.COMP_LINE = 'npm access '
   process.env.COMP_POINT = process.env.COMP_LINE.length
@@ -539,7 +538,7 @@ test('command completion errors propagate', t => {
   })
 })
 
-test('completion can complete flags', t => {
+t.test('completion can complete flags', t => {
   process.env.COMP_CWORD = 2
   process.env.COMP_LINE = 'npm install --'
   process.env.COMP_POINT = process.env.COMP_LINE.length
@@ -562,7 +561,7 @@ test('completion can complete flags', t => {
   })
 })
 
-test('double dashes escape from flag completion', t => {
+t.test('double dashes escape from flag completion', t => {
   process.env.COMP_CWORD = 2
   process.env.COMP_LINE = 'npm -- install --'
   process.env.COMP_POINT = process.env.COMP_LINE.length
@@ -585,7 +584,7 @@ test('double dashes escape from flag completion', t => {
   })
 })
 
-test('completion cannot complete options that take a value in mid-command', t => {
+t.test('completion cannot complete options that take a value in mid-command', t => {
   process.env.COMP_CWORD = 2
   process.env.COMP_LINE = 'npm --registry install'
   process.env.COMP_POINT = process.env.COMP_LINE.length
diff --git a/test/lib/config.js b/test/lib/config.js
index 074db976517e5..155ad0bcfb1b4 100644
--- a/test/lib/config.js
+++ b/test/lib/config.js
@@ -1,6 +1,5 @@
 const t = require('tap')
 
-const requireInject = require('require-inject')
 const { EventEmitter } = require('events')
 
 const redactCwd = (path) => {
@@ -84,7 +83,7 @@ const mocks = {
   '../../lib/utils/usage.js': usageUtil,
 }
 
-const Config = requireInject('../../lib/config.js', mocks)
+const Config = t.mock('../../lib/config.js', mocks)
 const config = new Config(npm)
 
 t.test('config no args', t => {
@@ -121,7 +120,7 @@ t.test('config list', t => {
   })
 
   config.exec(['list'], (err) => {
-    t.ifError(err, 'npm config list')
+    t.error(err, 'npm config list')
     t.matchSnapshot(result, 'should list configs')
   })
 })
@@ -147,7 +146,7 @@ t.test('config list overrides', t => {
   })
 
   config.exec(['list'], (err) => {
-    t.ifError(err, 'npm config list')
+    t.error(err, 'npm config list')
     t.matchSnapshot(result, 'should list overridden configs')
   })
 })
@@ -165,7 +164,7 @@ t.test('config list --long', t => {
   })
 
   config.exec(['list'], (err) => {
-    t.ifError(err, 'npm config list --long')
+    t.error(err, 'npm config list --long')
     t.matchSnapshot(result, 'should list all configs')
   })
 })
@@ -190,8 +189,8 @@ t.test('config list --json', t => {
   })
 
   config.exec(['list'], (err) => {
-    t.ifError(err, 'npm config list --json')
-    t.deepEqual(
+    t.error(err, 'npm config list --json')
+    t.same(
       JSON.parse(result),
       {
         editor: 'vi',
@@ -224,7 +223,7 @@ t.test('config delete key', t => {
   }
 
   config.exec(['delete', 'foo'], (err) => {
-    t.ifError(err, 'npm config delete key')
+    t.error(err, 'npm config delete key')
   })
 
   t.teardown(() => {
@@ -251,7 +250,7 @@ t.test('config delete multiple key', t => {
   }
 
   config.exec(['delete', 'foo', 'bar'], (err) => {
-    t.ifError(err, 'npm config delete keys')
+    t.error(err, 'npm config delete keys')
   })
 
   t.teardown(() => {
@@ -274,7 +273,7 @@ t.test('config delete key --global', t => {
 
   cliConfig.global = true
   config.exec(['delete', 'foo'], (err) => {
-    t.ifError(err, 'npm config delete key --global')
+    t.error(err, 'npm config delete key --global')
   })
 
   t.teardown(() => {
@@ -305,7 +304,7 @@ t.test('config set key', t => {
   }
 
   config.exec(['set', 'foo', 'bar'], (err) => {
-    t.ifError(err, 'npm config set key')
+    t.error(err, 'npm config set key')
   })
 
   t.teardown(() => {
@@ -328,7 +327,7 @@ t.test('config set key=val', t => {
   }
 
   config.exec(['set', 'foo=bar'], (err) => {
-    t.ifError(err, 'npm config set key')
+    t.error(err, 'npm config set key')
   })
 
   t.teardown(() => {
@@ -359,7 +358,7 @@ t.test('config set multiple keys', t => {
   }
 
   config.exec(['set', ...args], (err) => {
-    t.ifError(err, 'npm config set key')
+    t.error(err, 'npm config set key')
   })
 
   t.teardown(() => {
@@ -382,7 +381,7 @@ t.test('config set key to empty value', t => {
   }
 
   config.exec(['set', 'foo'], (err) => {
-    t.ifError(err, 'npm config set key to empty value')
+    t.error(err, 'npm config set key to empty value')
   })
 
   t.teardown(() => {
@@ -410,7 +409,7 @@ t.test('config set invalid key', t => {
   })
 
   config.exec(['set', 'foo', 'bar'], (err) => {
-    t.ifError(err, 'npm config set invalid key')
+    t.error(err, 'npm config set invalid key')
   })
 })
 
@@ -429,7 +428,7 @@ t.test('config set key --global', t => {
 
   cliConfig.global = true
   config.exec(['set', 'foo', 'bar'], (err) => {
-    t.ifError(err, 'npm config set key --global')
+    t.error(err, 'npm config set key --global')
   })
 
   t.teardown(() => {
@@ -450,7 +449,7 @@ t.test('config get no args', t => {
   })
 
   config.exec(['get'], (err) => {
-    t.ifError(err, 'npm config get no args')
+    t.error(err, 'npm config get no args')
     t.matchSnapshot(result, 'should list configs on config get no args')
   })
 })
@@ -469,7 +468,7 @@ t.test('config get key', t => {
   }
 
   config.exec(['get', 'foo'], (err) => {
-    t.ifError(err, 'npm config get key')
+    t.error(err, 'npm config get key')
   })
 
   t.teardown(() => {
@@ -497,7 +496,7 @@ t.test('config get multiple keys', t => {
   }
 
   config.exec(['get', 'foo', 'bar'], (err) => {
-    t.ifError(err, 'npm config get multiple keys')
+    t.error(err, 'npm config get multiple keys')
     t.equal(result, 'foo=asdf\nbar=asdf')
   })
 
@@ -555,20 +554,20 @@ sign-git-commit=true`
       },
     },
   }
-  const Config = requireInject('../../lib/config.js', editMocks)
+  const Config = t.mock('../../lib/config.js', editMocks)
   const config = new Config(npm)
 
   config.exec(['edit'], (err) => {
-    t.ifError(err, 'npm config edit')
+    t.error(err, 'npm config edit')
 
     // test no config file result
     editMocks.fs.readFile = (p, e, cb) => {
       cb(new Error('ERR'))
     }
-    const Config = requireInject('../../lib/config.js', editMocks)
+    const Config = t.mock('../../lib/config.js', editMocks)
     const config = new Config(npm)
     config.exec(['edit'], (err) => {
-      t.ifError(err, 'npm config edit')
+      t.error(err, 'npm config edit')
     })
   })
 
@@ -614,7 +613,7 @@ t.test('config edit --global', t => {
       },
     },
   }
-  const Config = requireInject('../../lib/config.js', editMocks)
+  const Config = t.mock('../../lib/config.js', editMocks)
   const config = new Config(npm)
   config.exec(['edit'], (err) => {
     t.match(err, /exited with code: 137/, 'propagated exit code from editor')
diff --git a/test/lib/dedupe.js b/test/lib/dedupe.js
index 851163f935e27..801e3c96de3cf 100644
--- a/test/lib/dedupe.js
+++ b/test/lib/dedupe.js
@@ -1,9 +1,8 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 const mockNpm = require('../fixtures/mock-npm')
 
-test('should throw in global mode', (t) => {
-  const Dedupe = requireInject('../../lib/dedupe.js')
+t.test('should throw in global mode', (t) => {
+  const Dedupe = t.mock('../../lib/dedupe.js')
   const npm = mockNpm({
     config: { 'dry-run': false, global: true },
   })
@@ -15,8 +14,8 @@ test('should throw in global mode', (t) => {
   })
 })
 
-test('should remove dupes using Arborist', (t) => {
-  const Dedupe = requireInject('../../lib/dedupe.js', {
+t.test('should remove dupes using Arborist', (t) => {
+  const Dedupe = t.mock('../../lib/dedupe.js', {
     '@npmcli/arborist': function (args) {
       t.ok(args, 'gets options object')
       t.ok(args.path, 'gets path option')
@@ -44,8 +43,8 @@ test('should remove dupes using Arborist', (t) => {
   })
 })
 
-test('should remove dupes using Arborist - no arguments', (t) => {
-  const Dedupe = requireInject('../../lib/dedupe.js', {
+t.test('should remove dupes using Arborist - no arguments', (t) => {
+  const Dedupe = t.mock('../../lib/dedupe.js', {
     '@npmcli/arborist': function (args) {
       t.ok(args.dryRun, 'gets dryRun from config')
       this.dedupe = () => {}
diff --git a/test/lib/deprecate.js b/test/lib/deprecate.js
index e278a3e3ca7c7..c358fde247955 100644
--- a/test/lib/deprecate.js
+++ b/test/lib/deprecate.js
@@ -1,5 +1,4 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 
 let getIdentityImpl = () => 'someperson'
 let npmFetchBody = null
@@ -18,7 +17,7 @@ npmFetch.json = async (uri, opts) => {
   }
 }
 
-const Deprecate = requireInject('../../lib/deprecate.js', {
+const Deprecate = t.mock('../../lib/deprecate.js', {
   '../../lib/utils/get-identity.js': async () => getIdentityImpl(),
   '../../lib/utils/otplease.js': async (opts, fn) => fn(opts),
   libnpmaccess: {
@@ -31,7 +30,7 @@ const deprecate = new Deprecate({
   flatOptions: { registry: 'https://registry.npmjs.org' },
 })
 
-test('completion', async t => {
+t.test('completion', async t => {
   const defaultIdentityImpl = getIdentityImpl
   t.teardown(() => {
     getIdentityImpl = defaultIdentityImpl
@@ -58,28 +57,28 @@ test('completion', async t => {
   t.rejects(testComp([], []), { message: 'deprecate test failure' })
 })
 
-test('no args', t => {
+t.test('no args', t => {
   deprecate.exec([], (err) => {
     t.match(err, 'Usage:', 'logs usage')
     t.end()
   })
 })
 
-test('only one arg', t => {
+t.test('only one arg', t => {
   deprecate.exec(['foo'], (err) => {
     t.match(err, 'Usage:', 'logs usage')
     t.end()
   })
 })
 
-test('invalid semver range', t => {
+t.test('invalid semver range', t => {
   deprecate.exec(['foo@notaversion', 'this will fail'], (err) => {
     t.match(err, /invalid version range/, 'logs semver error')
     t.end()
   })
 })
 
-test('deprecates given range', t => {
+t.test('deprecates given range', t => {
   t.teardown(() => {
     npmFetchBody = null
   })
@@ -105,7 +104,7 @@ test('deprecates given range', t => {
   })
 })
 
-test('deprecates all versions when no range is specified', t => {
+t.test('deprecates all versions when no range is specified', t => {
   t.teardown(() => {
     npmFetchBody = null
   })
diff --git a/test/lib/diff.js b/test/lib/diff.js
index 08761c64c86b4..355095c95786e 100644
--- a/test/lib/diff.js
+++ b/test/lib/diff.js
@@ -1,6 +1,5 @@
 const { resolve } = require('path')
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 
 const noop = () => null
@@ -38,7 +37,7 @@ const mocks = {
   '../../lib/utils/usage.js': () => 'usage instructions',
 }
 
-t.afterEach(cb => {
+t.afterEach(() => {
   config.global = false
   config.tag = 'latest'
   config.diff = []
@@ -54,10 +53,9 @@ t.afterEach(cb => {
   npm.prefix = '..'
   libnpmdiff = noop
   rlp = () => 'foo'
-  cb()
 })
 
-const Diff = requireInject('../../lib/diff.js', mocks)
+const Diff = t.mock('../../lib/diff.js', mocks)
 const diff = new Diff(npm)
 
 t.test('no args', t => {
@@ -314,7 +312,7 @@ t.test('single arg', t => {
     config.diff = ['bar']
     npm.prefix = path
 
-    const Diff = requireInject('../../lib/diff.js', {
+    const Diff = t.mock('../../lib/diff.js', {
       ...mocks,
       pacote: {
         packument: (spec) => {
@@ -378,7 +376,7 @@ t.test('single arg', t => {
     npm.prefix = resolve(path, 'project')
     npm.globalDir = resolve(path, 'globalDir/lib/node_modules')
 
-    const Diff = requireInject('../../lib/diff.js', {
+    const Diff = t.mock('../../lib/diff.js', {
       ...mocks,
       pacote: {
         packument: (spec) => {
@@ -465,7 +463,7 @@ t.test('single arg', t => {
       }),
     })
 
-    const Diff = requireInject('../../lib/diff.js', {
+    const Diff = t.mock('../../lib/diff.js', {
       ...mocks,
       '../../lib/utils/read-local-package.js': async () => 'my-project',
       pacote: {
@@ -502,7 +500,7 @@ t.test('single arg', t => {
       }),
     })
 
-    const Diff = requireInject('../../lib/diff.js', {
+    const Diff = t.mock('../../lib/diff.js', {
       ...mocks,
       '../../lib/utils/read-local-package.js': async () => 'my-project',
       '@npmcli/arborist': class {
@@ -940,7 +938,7 @@ t.test('first arg is a valid semver range', t => {
       }),
     })
 
-    const Diff = requireInject('../../lib/diff.js', {
+    const Diff = t.mock('../../lib/diff.js', {
       ...mocks,
       '../../lib/utils/read-local-package.js': async () => 'my-project',
       '@npmcli/arborist': class {
diff --git a/test/lib/dist-tag.js b/test/lib/dist-tag.js
index 5e54c8f991cfd..701bdc6e48c35 100644
--- a/test/lib/dist-tag.js
+++ b/test/lib/dist-tag.js
@@ -1,14 +1,12 @@
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
-const { afterEach, test } = require('tap')
+const t = require('tap')
 
 let result = ''
 let log = ''
 
-afterEach((cb) => {
+t.afterEach(() => {
   result = ''
   log = ''
-  cb()
 })
 
 const routeMap = {
@@ -58,7 +56,7 @@ const logger = (...msgs) => {
   log += '\n'
 }
 
-const DistTag = requireInject('../../lib/dist-tag.js', {
+const DistTag = t.mock('../../lib/dist-tag.js', {
   npmlog: {
     error: logger,
     info: logger,
@@ -80,14 +78,14 @@ const npm = mockNpm({
 })
 const distTag = new DistTag(npm)
 
-test('ls in current package', (t) => {
+t.test('ls in current package', (t) => {
   npm.prefix = t.testdir({
     'package.json': JSON.stringify({
       name: '@scoped/pkg',
     }),
   })
   distTag.exec(['ls'], (err) => {
-    t.ifError(err, 'npm dist-tags ls')
+    t.error(err, 'npm dist-tags ls')
     t.matchSnapshot(
       result,
       'should list available tags for current package'
@@ -96,14 +94,14 @@ test('ls in current package', (t) => {
   })
 })
 
-test('no args in current package', (t) => {
+t.test('no args in current package', (t) => {
   npm.prefix = t.testdir({
     'package.json': JSON.stringify({
       name: '@scoped/pkg',
     }),
   })
   distTag.exec([], (err) => {
-    t.ifError(err, 'npm dist-tags ls')
+    t.error(err, 'npm dist-tags ls')
     t.matchSnapshot(
       result,
       'should default to listing available tags for current package'
@@ -112,7 +110,7 @@ test('no args in current package', (t) => {
   })
 })
 
-test('borked cmd usage', (t) => {
+t.test('borked cmd usage', (t) => {
   npm.prefix = t.testdir({})
   distTag.exec(['borked', '@scoped/pkg'], (err) => {
     t.matchSnapshot(err, 'should show usage error')
@@ -120,10 +118,10 @@ test('borked cmd usage', (t) => {
   })
 })
 
-test('ls on named package', (t) => {
+t.test('ls on named package', (t) => {
   npm.prefix = t.testdir({})
   distTag.exec(['ls', '@scoped/another'], (err) => {
-    t.ifError(err, 'npm dist-tags ls')
+    t.error(err, 'npm dist-tags ls')
     t.matchSnapshot(
       result,
       'should list tags for the specified package'
@@ -132,7 +130,7 @@ test('ls on named package', (t) => {
   })
 })
 
-test('ls on missing package', (t) => {
+t.test('ls on missing package', (t) => {
   npm.prefix = t.testdir({})
   distTag.exec(['ls', 'foo'], (err) => {
     t.matchSnapshot(
@@ -147,7 +145,7 @@ test('ls on missing package', (t) => {
   })
 })
 
-test('ls on missing name in current package', (t) => {
+t.test('ls on missing name in current package', (t) => {
   npm.prefix = t.testdir({
     'package.json': JSON.stringify({
       version: '1.0.0',
@@ -162,10 +160,10 @@ test('ls on missing name in current package', (t) => {
   })
 })
 
-test('only named package arg', (t) => {
+t.test('only named package arg', (t) => {
   npm.prefix = t.testdir({})
   distTag.exec(['@scoped/another'], (err) => {
-    t.ifError(err, 'npm dist-tags ls')
+    t.error(err, 'npm dist-tags ls')
     t.matchSnapshot(
       result,
       'should default to listing tags for the specified package'
@@ -174,7 +172,7 @@ test('only named package arg', (t) => {
   })
 })
 
-test('workspaces', (t) => {
+t.test('workspaces', (t) => {
   npm.localPrefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'root',
@@ -203,7 +201,7 @@ test('workspaces', (t) => {
 
   t.test('no args', t => {
     distTag.execWorkspaces([], [], (err) => {
-      t.ifError(err)
+      t.error(err)
       t.matchSnapshot(result, 'printed the expected output')
       t.end()
     })
@@ -211,7 +209,7 @@ test('workspaces', (t) => {
 
   t.test('no args, one workspace', t => {
     distTag.execWorkspaces([], ['workspace-a'], (err) => {
-      t.ifError(err)
+      t.error(err)
       t.matchSnapshot(result, 'printed the expected output')
       t.end()
     })
@@ -219,7 +217,7 @@ test('workspaces', (t) => {
 
   t.test('one arg -- .', t => {
     distTag.execWorkspaces(['.'], [], (err) => {
-      t.ifError(err)
+      t.error(err)
       t.matchSnapshot(result, 'printed the expected output')
       t.end()
     })
@@ -227,7 +225,7 @@ test('workspaces', (t) => {
 
   t.test('one arg -- .@1, ignores version spec', t => {
     distTag.execWorkspaces(['.@'], [], (err) => {
-      t.ifError(err)
+      t.error(err)
       t.matchSnapshot(result, 'printed the expected output')
       t.end()
     })
@@ -235,7 +233,7 @@ test('workspaces', (t) => {
 
   t.test('one arg -- list', t => {
     distTag.execWorkspaces(['list'], [], (err) => {
-      t.ifError(err)
+      t.error(err)
       t.matchSnapshot(result, 'printed the expected output')
       t.end()
     })
@@ -243,7 +241,7 @@ test('workspaces', (t) => {
 
   t.test('two args -- list, .', t => {
     distTag.execWorkspaces(['list', '.'], [], (err) => {
-      t.ifError(err)
+      t.error(err)
       t.matchSnapshot(result, 'printed the expected output')
       t.end()
     })
@@ -251,7 +249,7 @@ test('workspaces', (t) => {
 
   t.test('two args -- list, .@1, ignores version spec', t => {
     distTag.execWorkspaces(['list', '.@'], [], (err) => {
-      t.ifError(err)
+      t.error(err)
       t.matchSnapshot(result, 'printed the expected output')
       t.end()
     })
@@ -259,7 +257,7 @@ test('workspaces', (t) => {
 
   t.test('two args -- list, @scoped/pkg, logs a warning and ignores workspaces', t => {
     distTag.execWorkspaces(['list', '@scoped/pkg'], [], (err) => {
-      t.ifError(err)
+      t.error(err)
       t.match(log, 'Ignoring workspaces for specified package', 'logs a warning')
       t.matchSnapshot(result, 'printed the expected output')
       t.end()
@@ -300,7 +298,7 @@ test('workspaces', (t) => {
     })
 
     distTag.execWorkspaces([], [], (err) => {
-      t.ifError(err)
+      t.error(err)
       t.equal(process.exitCode, 1, 'set the error status')
       process.exitCode = 0
       t.match(log, 'dist-tag ls Couldn\'t get dist-tag data for workspace-d@latest', 'logs the error')
@@ -312,7 +310,7 @@ test('workspaces', (t) => {
   t.end()
 })
 
-test('add new tag', (t) => {
+t.test('add new tag', (t) => {
   const _nrf = npmRegistryFetchMock
   t.teardown(() => {
     npmRegistryFetchMock = _nrf
@@ -324,7 +322,7 @@ test('add new tag', (t) => {
   }
   npm.prefix = t.testdir({})
   distTag.exec(['add', '@scoped/another@7.7.7', 'c'], (err) => {
-    t.ifError(err, 'npm dist-tags add')
+    t.error(err, 'npm dist-tags add')
     t.matchSnapshot(
       result,
       'should return success msg'
@@ -333,7 +331,7 @@ test('add new tag', (t) => {
   })
 })
 
-test('add using valid semver range as name', (t) => {
+t.test('add using valid semver range as name', (t) => {
   npm.prefix = t.testdir({})
   distTag.exec(['add', '@scoped/another@7.7.7', '1.0.0'], (err) => {
     t.match(
@@ -349,7 +347,7 @@ test('add using valid semver range as name', (t) => {
   })
 })
 
-test('add missing args', (t) => {
+t.test('add missing args', (t) => {
   npm.prefix = t.testdir({})
   distTag.exec(['add', '@scoped/another@7.7.7'], (err) => {
     t.matchSnapshot(err, 'should exit usage error message')
@@ -357,7 +355,7 @@ test('add missing args', (t) => {
   })
 })
 
-test('add missing pkg name', (t) => {
+t.test('add missing pkg name', (t) => {
   npm.prefix = t.testdir({})
   distTag.exec(['add', null], (err) => {
     t.matchSnapshot(err, 'should exit usage error message')
@@ -365,10 +363,10 @@ test('add missing pkg name', (t) => {
   })
 })
 
-test('set existing version', (t) => {
+t.test('set existing version', (t) => {
   npm.prefix = t.testdir({})
   distTag.exec(['set', '@scoped/another@0.6.0', 'b'], (err) => {
-    t.ifError(err, 'npm dist-tags set')
+    t.error(err, 'npm dist-tags set')
     t.matchSnapshot(
       log,
       'should log warn msg'
@@ -377,7 +375,7 @@ test('set existing version', (t) => {
   })
 })
 
-test('remove existing tag', (t) => {
+t.test('remove existing tag', (t) => {
   const _nrf = npmRegistryFetchMock
   t.teardown(() => {
     npmRegistryFetchMock = _nrf
@@ -388,14 +386,14 @@ test('remove existing tag', (t) => {
   }
   npm.prefix = t.testdir({})
   distTag.exec(['rm', '@scoped/another', 'c'], (err) => {
-    t.ifError(err, 'npm dist-tags rm')
+    t.error(err, 'npm dist-tags rm')
     t.matchSnapshot(log, 'should log remove info')
     t.matchSnapshot(result, 'should return success msg')
     t.end()
   })
 })
 
-test('remove non-existing tag', (t) => {
+t.test('remove non-existing tag', (t) => {
   npm.prefix = t.testdir({})
   distTag.exec(['rm', '@scoped/another', 'nonexistent'], (err) => {
     t.match(
@@ -408,7 +406,7 @@ test('remove non-existing tag', (t) => {
   })
 })
 
-test('remove missing pkg name', (t) => {
+t.test('remove missing pkg name', (t) => {
   npm.prefix = t.testdir({})
   distTag.exec(['rm', null], (err) => {
     t.matchSnapshot(err, 'should exit usage error message')
@@ -416,7 +414,7 @@ test('remove missing pkg name', (t) => {
   })
 })
 
-test('completion', t => {
+t.test('completion', t => {
   const { completion } = distTag
   t.plan(2)
 
diff --git a/test/lib/docs.js b/test/lib/docs.js
index e8176eb47bdf9..0da070d9a7d13 100644
--- a/test/lib/docs.js
+++ b/test/lib/docs.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm.js')
 const { join, sep } = require('path')
 
@@ -72,16 +71,14 @@ const openUrl = async (npm, url, errMsg) => {
   opened[url]++
 }
 
-const Docs = requireInject('../../lib/docs.js', {
+const Docs = t.mock('../../lib/docs.js', {
   '../../lib/utils/open-url.js': openUrl,
 })
 const flatOptions = {}
 const npm = mockNpm({ flatOptions })
 const docs = new Docs(npm)
 
-t.afterEach(async () => {
-  opened = {}
-})
+t.afterEach(() => opened = {})
 
 t.test('open docs urls', t => {
   // XXX It is very odd that `where` is how pacote knows to look anywhere other
diff --git a/test/lib/doctor.js b/test/lib/doctor.js
index 56bbdf974491d..0ceb670c15054 100644
--- a/test/lib/doctor.js
+++ b/test/lib/doctor.js
@@ -1,5 +1,4 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 
 const { join } = require('path')
 const fs = require('fs')
@@ -123,7 +122,7 @@ const cacache = {
   },
 }
 
-const Doctor = requireInject('../../lib/doctor.js', {
+const Doctor = t.mock('../../lib/doctor.js', {
   '../../lib/utils/is-windows.js': false,
   '../../lib/utils/ping.js': ping,
   cacache,
@@ -134,7 +133,7 @@ const Doctor = requireInject('../../lib/doctor.js', {
 const doctor = new Doctor(npm)
 
 const origVersion = process.version
-test('node versions', t => {
+t.test('node versions', t => {
   t.plan(nodeVersions.length)
 
   nodeVersions.forEach(({ version }) => {
@@ -276,13 +275,13 @@ test('node versions', t => {
           st.match(output, /local bin folder.*ok/, 'local bin is ok')
           st.match(output, /global bin folder.*ok/, 'global bin is ok')
           st.match(output, /cache contents.*ok/, 'cache contents is ok')
-          st.notEqual(output[0], ansiTrim(output[0]), 'output should contain color codes')
+          st.not(output[0], ansiTrim(output[0]), 'output should contain color codes')
           st.end()
         })
       })
 
       vt.test('npm doctor skips some tests in windows', st => {
-        const WinDoctor = requireInject('../../lib/doctor.js', {
+        const WinDoctor = t.mock('../../lib/doctor.js', {
           '../../lib/utils/is-windows.js': true,
           '../../lib/utils/ping.js': ping,
           cacache,
@@ -560,7 +559,7 @@ test('node versions', t => {
           }
         }
 
-        const Doctor = requireInject('../../lib/doctor.js', {
+        const Doctor = t.mock('../../lib/doctor.js', {
           '../../lib/utils/is-windows.js': false,
           '../../lib/utils/ping.js': ping,
           cacache,
@@ -903,7 +902,7 @@ test('node versions', t => {
   })
 })
 
-test('outdated node version', vt => {
+t.test('outdated node version', vt => {
   vt.plan(1)
   const version = 'v10.0.0'
 
diff --git a/test/lib/edit.js b/test/lib/edit.js
index acf03fa438c3c..09908165d7722 100644
--- a/test/lib/edit.js
+++ b/test/lib/edit.js
@@ -1,6 +1,5 @@
-const { test } = require('tap')
+const t = require('tap')
 const { resolve } = require('path')
-const requireInject = require('require-inject')
 const { EventEmitter } = require('events')
 
 let editorBin = null
@@ -39,13 +38,13 @@ const npm = {
 }
 
 const gracefulFs = require('graceful-fs')
-const Edit = requireInject('../../lib/edit.js', {
+const Edit = t.mock('../../lib/edit.js', {
   child_process: childProcess,
   'graceful-fs': gracefulFs,
 })
 const edit = new Edit(npm)
 
-test('npm edit', t => {
+t.test('npm edit', t => {
   t.teardown(() => {
     rebuildArgs = null
     editorBin = null
@@ -66,7 +65,7 @@ test('npm edit', t => {
   })
 })
 
-test('rebuild fails', t => {
+t.test('rebuild fails', t => {
   t.teardown(() => {
     rebuildFail = null
     rebuildArgs = null
@@ -87,7 +86,7 @@ test('rebuild fails', t => {
   })
 })
 
-test('npm edit editor has flags', t => {
+t.test('npm edit editor has flags', t => {
   EDITOR = 'code -w'
   t.teardown(() => {
     rebuildArgs = null
@@ -110,14 +109,14 @@ test('npm edit editor has flags', t => {
   })
 })
 
-test('npm edit no args', t => {
+t.test('npm edit no args', t => {
   return edit.exec([], (err) => {
     t.match(err, /npm edit/, 'throws usage error')
     t.end()
   })
 })
 
-test('npm edit lstat error propagates', t => {
+t.test('npm edit lstat error propagates', t => {
   const _lstat = gracefulFs.lstat
   gracefulFs.lstat = (dir, cb) => {
     return cb(new Error('lstat failed'))
@@ -132,7 +131,7 @@ test('npm edit lstat error propagates', t => {
   })
 })
 
-test('npm edit editor exit code error propagates', t => {
+t.test('npm edit editor exit code error propagates', t => {
   EDITOR_CODE = 137
   t.teardown(() => {
     EDITOR_CODE = 0
diff --git a/test/lib/exec.js b/test/lib/exec.js
index bcfe75577ce27..0c577e42f620d 100644
--- a/test/lib/exec.js
+++ b/test/lib/exec.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 const { resolve, delimiter } = require('path')
 const OUTPUT = []
@@ -94,10 +93,10 @@ const mocks = {
   read,
   'mkdirp-infer-owner': mkdirp,
 }
-const Exec = requireInject('../../lib/exec.js', mocks)
+const Exec = t.mock('../../lib/exec.js', mocks)
 const exec = new Exec(npm)
 
-t.afterEach(cb => {
+t.afterEach(() => {
   MKDIRPS.length = 0
   ARB_CTOR.length = 0
   ARB_REIFY.length = 0
@@ -115,7 +114,6 @@ t.afterEach(cb => {
   config.yes = true
   npm.localBin = 'local-bin'
   npm.globalBin = 'global-bin'
-  cb()
 })
 
 t.test('npx foo, bin already exists locally', t => {
@@ -127,7 +125,7 @@ t.test('npx foo, bin already exists locally', t => {
   npm.localBin = path
 
   exec.exec(['foo', 'one arg', 'two arg'], er => {
-    t.ifError(er, 'npm exec')
+    t.error(er, 'npm exec')
     t.match(RUN_SCRIPTS, [{
       pkg: { scripts: { npx: 'foo' }},
       args: ['one arg', 'two arg'],
@@ -153,7 +151,7 @@ t.test('npx foo, bin already exists globally', t => {
   npm.globalBin = path
 
   exec.exec(['foo', 'one arg', 'two arg'], er => {
-    t.ifError(er, 'npm exec')
+    t.error(er, 'npm exec')
     t.match(RUN_SCRIPTS, [{
       pkg: { scripts: { npx: 'foo' }},
       args: ['one arg', 'two arg'],
@@ -1067,7 +1065,7 @@ t.test('abort if -n provided', t => {
     t.equal(PROGRESS_ENABLED, true, 'progress re-enabled')
     t.strictSame(RUN_SCRIPTS, [])
     t.strictSame(READ, [])
-    t.done()
+    t.end()
   })
 })
 
@@ -1095,7 +1093,7 @@ t.test('forward legacyPeerDeps opt', t => {
     if (er)
       throw er
     t.match(ARB_REIFY, [{add: ['foo@'], legacyPeerDeps: true}], 'need to install foo@ using legacyPeerDeps opt')
-    t.done()
+    t.end()
   })
 })
 
diff --git a/test/lib/explain.js b/test/lib/explain.js
index 2e82928d89d19..7e4ec8bd37bff 100644
--- a/test/lib/explain.js
+++ b/test/lib/explain.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const npm = {
   prefix: null,
   color: true,
@@ -12,7 +11,7 @@ const { resolve } = require('path')
 
 const OUTPUT = []
 
-const Explain = requireInject('../../lib/explain.js', {
+const Explain = t.mock('../../lib/explain.js', {
 
   // keep the snapshots pared down a bit, since this has its own tests.
   '../../lib/utils/explain-dep.js': {
@@ -27,7 +26,7 @@ t.test('no args throws usage', t => {
   t.plan(1)
   explain.exec([], er => {
     t.equal(er, explain.usage)
-    t.done()
+    t.end()
   })
 })
 
@@ -49,10 +48,9 @@ t.test('invalid package name throws not found', t => {
 })
 
 t.test('explain some nodes', t => {
-  t.afterEach((cb) => {
+  t.afterEach(() => {
     OUTPUT.length = 0
     npm.flatOptions.json = false
-    cb()
   })
 
   npm.prefix = t.testdir({
@@ -172,7 +170,7 @@ t.test('explain some nodes', t => {
     t.plan(1)
     explain.exec(['asdf/foo/bar', 'quux@1.x'], er => {
       t.equal(er, 'No dependencies found matching asdf/foo/bar, quux@1.x')
-      t.done()
+      t.end()
     })
   })
   t.end()
diff --git a/test/lib/explore.js b/test/lib/explore.js
index a0655380e5583..b49c885cbcb26 100644
--- a/test/lib/explore.js
+++ b/test/lib/explore.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 
 let RPJ_ERROR = null
 let RPJ_CALLED = ''
@@ -47,7 +46,7 @@ const output = []
 let ERROR_HANDLER_CALLED = null
 const logs = []
 const getExplore = (windows) => {
-  const Explore = requireInject('../../lib/explore.js', {
+  const Explore = t.mock('../../lib/explore.js', {
     '../../lib/utils/is-windows.js': windows,
     path: require('path')[windows ? 'win32' : 'posix'],
     '../../lib/utils/error-handler.js': er => {
@@ -77,10 +76,7 @@ const windowsExplore = getExplore(true)
 const posixExplore = getExplore(false)
 
 t.test('basic interactive', t => {
-  t.afterEach((cb) => {
-    output.length = 0
-    cb()
-  })
+  t.afterEach(() => output.length = 0)
 
   t.test('windows', t => windowsExplore.exec(['pkg'], er => {
     if (er)
@@ -125,16 +121,14 @@ t.test('basic interactive', t => {
 
 t.test('interactive tracks exit code', t => {
   const { exitCode } = process
-  t.beforeEach((cb) => {
+  t.beforeEach(() => {
     process.exitCode = exitCode
     RUN_SCRIPT_EXIT_CODE = 99
-    cb()
   })
-  t.afterEach((cb) => {
+  t.afterEach(() => {
     RUN_SCRIPT_EXIT_CODE = 0
     output.length = 0
     process.exitCode = exitCode
-    cb()
   })
 
   t.test('windows', t => windowsExplore.exec(['pkg'], er => {
@@ -223,10 +217,7 @@ t.test('interactive tracks exit code', t => {
 })
 
 t.test('basic non-interactive', t => {
-  t.afterEach((cb) => {
-    output.length = 0
-    cb()
-  })
+  t.afterEach(() => output.length = 0)
 
   t.test('windows', t => windowsExplore.exec(['pkg', 'ls'], er => {
     if (er)
@@ -267,22 +258,17 @@ t.test('basic non-interactive', t => {
 
 t.test('signal fails non-interactive', t => {
   const { exitCode } = process
-  t.afterEach((cb) => {
+  t.afterEach(() => {
     output.length = 0
     logs.length = 0
-    cb()
   })
 
-  t.beforeEach(cb => {
+  t.beforeEach(() => {
     RUN_SCRIPT_SIGNAL = 'SIGPROBLEM'
     RUN_SCRIPT_EXIT_CODE = null
     process.exitCode = exitCode
-    cb()
-  })
-  t.afterEach(cb => {
-    process.exitCode = exitCode
-    cb()
   })
+  t.afterEach(() => process.exitCode = exitCode)
 
   t.test('windows', t => windowsExplore.exec(['pkg', 'ls'], er => {
     t.match(er, {
diff --git a/test/lib/fund.js b/test/lib/fund.js
index 8c10007844f0a..41754d51f3589 100644
--- a/test/lib/fund.js
+++ b/test/lib/fund.js
@@ -1,5 +1,4 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 const mockNpm = require('../fixtures/mock-npm')
 
 const version = '1.0.0'
@@ -200,7 +199,7 @@ const openUrl = async (npm, url, msg) => {
   } else
     printUrl = `${msg}:\n  ${url}`
 }
-const Fund = requireInject('../../lib/fund.js', {
+const Fund = t.mock('../../lib/fund.js', {
   '../../lib/utils/open-url.js': openUrl,
   pacote: {
     manifest: (arg) => arg.name === 'ntl'
@@ -218,7 +217,7 @@ const npm = mockNpm({
 })
 const fund = new Fund(npm)
 
-test('fund with no package containing funding', t => {
+t.test('fund with no package containing funding', t => {
   npm.prefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'no-funding-package',
@@ -227,31 +226,31 @@ test('fund with no package containing funding', t => {
   })
 
   fund.exec([], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.matchSnapshot(result, 'should print empty funding info')
     result = ''
     t.end()
   })
 })
 
-test('fund in which same maintainer owns all its deps', t => {
+t.test('fund in which same maintainer owns all its deps', t => {
   npm.prefix = t.testdir(maintainerOwnsAllDeps)
 
   fund.exec([], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.matchSnapshot(result, 'should print stack packages together')
     result = ''
     t.end()
   })
 })
 
-test('fund in which same maintainer owns all its deps, using --json option', t => {
+t.test('fund in which same maintainer owns all its deps, using --json option', t => {
   config.json = true
   npm.prefix = t.testdir(maintainerOwnsAllDeps)
 
   fund.exec([], (err) => {
-    t.ifError(err, 'should not error out')
-    t.deepEqual(
+    t.error(err, 'should not error out')
+    t.same(
       JSON.parse(result),
       {
         length: 3,
@@ -284,11 +283,11 @@ test('fund in which same maintainer owns all its deps, using --json option', t =
   })
 })
 
-test('fund containing multi-level nested deps with no funding', t => {
+t.test('fund containing multi-level nested deps with no funding', t => {
   npm.prefix = t.testdir(nestedNoFundingPackages)
 
   fund.exec([], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.matchSnapshot(
       result,
       'should omit dependencies with no funding declared'
@@ -299,13 +298,13 @@ test('fund containing multi-level nested deps with no funding', t => {
   })
 })
 
-test('fund containing multi-level nested deps with no funding, using --json option', t => {
+t.test('fund containing multi-level nested deps with no funding, using --json option', t => {
   npm.prefix = t.testdir(nestedNoFundingPackages)
   config.json = true
 
   fund.exec([], (err) => {
-    t.ifError(err, 'should not error out')
-    t.deepEqual(
+    t.error(err, 'should not error out')
+    t.same(
       JSON.parse(result),
       {
         length: 2,
@@ -331,13 +330,13 @@ test('fund containing multi-level nested deps with no funding, using --json opti
   })
 })
 
-test('fund containing multi-level nested deps with no funding, using --json option', t => {
+t.test('fund containing multi-level nested deps with no funding, using --json option', t => {
   npm.prefix = t.testdir(nestedMultipleFundingPackages)
   config.json = true
 
   fund.exec([], (err) => {
-    t.ifError(err, 'should not error out')
-    t.deepEqual(
+    t.error(err, 'should not error out')
+    t.same(
       JSON.parse(result),
       {
         length: 2,
@@ -388,7 +387,7 @@ test('fund containing multi-level nested deps with no funding, using --json opti
   })
 })
 
-test('fund does not support global', t => {
+t.test('fund does not support global', t => {
   npm.prefix = t.testdir({})
   config.global = true
 
@@ -401,11 +400,11 @@ test('fund does not support global', t => {
   })
 })
 
-test('fund using package argument', t => {
+t.test('fund using package argument', t => {
   npm.prefix = t.testdir(maintainerOwnsAllDeps)
 
   fund.exec(['.'], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.matchSnapshot(printUrl, 'should open funding url')
 
     printUrl = ''
@@ -413,7 +412,7 @@ test('fund using package argument', t => {
   })
 })
 
-test('fund does not support global, using --json option', t => {
+t.test('fund does not support global, using --json option', t => {
   npm.prefix = t.testdir({})
   config.global = true
   config.json = true
@@ -432,7 +431,7 @@ test('fund does not support global, using --json option', t => {
   })
 })
 
-test('fund using string shorthand', t => {
+t.test('fund using string shorthand', t => {
   npm.prefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'funding-string-shorthand',
@@ -442,7 +441,7 @@ test('fund using string shorthand', t => {
   })
 
   fund.exec(['.'], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.matchSnapshot(printUrl, 'should open string-only url')
 
     printUrl = ''
@@ -450,11 +449,11 @@ test('fund using string shorthand', t => {
   })
 })
 
-test('fund using nested packages with multiple sources', t => {
+t.test('fund using nested packages with multiple sources', t => {
   npm.prefix = t.testdir(nestedMultipleFundingPackages)
 
   fund.exec(['.'], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.matchSnapshot(result, 'should prompt with all available URLs')
 
     result = ''
@@ -462,7 +461,7 @@ test('fund using nested packages with multiple sources', t => {
   })
 })
 
-test('fund using symlink ref', t => {
+t.test('fund using symlink ref', t => {
   npm.prefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'using-symlink-ref',
@@ -482,7 +481,7 @@ test('fund using symlink ref', t => {
 
   // using symlinked ref
   fund.exec(['./node_modules/a'], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.match(
       printUrl,
       'http://example.com/a',
@@ -493,7 +492,7 @@ test('fund using symlink ref', t => {
 
     // using target ref
     fund.exec(['./a'], (err) => {
-      t.ifError(err, 'should not error out')
+      t.error(err, 'should not error out')
 
       t.match(
         printUrl,
@@ -508,7 +507,7 @@ test('fund using symlink ref', t => {
   })
 })
 
-test('fund using data from actual tree', t => {
+t.test('fund using data from actual tree', t => {
   npm.prefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'using-actual-tree',
@@ -543,7 +542,7 @@ test('fund using data from actual tree', t => {
 
   // using symlinked ref
   fund.exec(['a'], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.match(
       printUrl,
       'http://example.com/_AAA',
@@ -555,12 +554,12 @@ test('fund using data from actual tree', t => {
   })
 })
 
-test('fund using nested packages with multiple sources, with a source number', t => {
+t.test('fund using nested packages with multiple sources, with a source number', t => {
   npm.prefix = t.testdir(nestedMultipleFundingPackages)
   config.which = '1'
 
   fund.exec(['.'], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.matchSnapshot(printUrl, 'should open the numbered URL')
 
     config.which = null
@@ -569,12 +568,12 @@ test('fund using nested packages with multiple sources, with a source number', t
   })
 })
 
-test('fund using pkg name while having conflicting versions', t => {
+t.test('fund using pkg name while having conflicting versions', t => {
   npm.prefix = t.testdir(conflictingFundingPackages)
   config.which = '1'
 
   fund.exec(['foo'], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.matchSnapshot(printUrl, 'should open greatest version')
 
     printUrl = ''
@@ -582,13 +581,13 @@ test('fund using pkg name while having conflicting versions', t => {
   })
 })
 
-test('fund using package argument with no browser, using --json option', t => {
+t.test('fund using package argument with no browser, using --json option', t => {
   npm.prefix = t.testdir(maintainerOwnsAllDeps)
   config.json = true
 
   fund.exec(['.'], (err) => {
-    t.ifError(err, 'should not error out')
-    t.deepEqual(
+    t.error(err, 'should not error out')
+    t.same(
       JSON.parse(printUrl),
       {
         title: 'individual funding available at the following URL',
@@ -603,11 +602,11 @@ test('fund using package argument with no browser, using --json option', t => {
   })
 })
 
-test('fund using package info fetch from registry', t => {
+t.test('fund using package info fetch from registry', t => {
   npm.prefix = t.testdir({})
 
   fund.exec(['ntl'], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.match(
       printUrl,
       /http:\/\/example.com\/pacote/,
@@ -619,7 +618,7 @@ test('fund using package info fetch from registry', t => {
   })
 })
 
-test('fund tries to use package info fetch from registry but registry has nothing', t => {
+t.test('fund tries to use package info fetch from registry but registry has nothing', t => {
   npm.prefix = t.testdir({})
 
   fund.exec(['foo'], (err) => {
@@ -635,7 +634,7 @@ test('fund tries to use package info fetch from registry but registry has nothin
   })
 })
 
-test('fund but target module has no funding info', t => {
+t.test('fund but target module has no funding info', t => {
   npm.prefix = t.testdir(nestedNoFundingPackages)
 
   fund.exec(['foo'], (err) => {
@@ -651,7 +650,7 @@ test('fund but target module has no funding info', t => {
   })
 })
 
-test('fund using bad which value', t => {
+t.test('fund using bad which value', t => {
   npm.prefix = t.testdir(nestedMultipleFundingPackages)
   config.which = 3
 
@@ -669,7 +668,7 @@ test('fund using bad which value', t => {
   })
 })
 
-test('fund pkg missing version number', t => {
+t.test('fund pkg missing version number', t => {
   npm.prefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'foo',
@@ -678,14 +677,14 @@ test('fund pkg missing version number', t => {
   })
 
   fund.exec([], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.matchSnapshot(result, 'should print name only')
     result = ''
     t.end()
   })
 })
 
-test('fund a package throws on openUrl', t => {
+t.test('fund a package throws on openUrl', t => {
   npm.prefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'foo',
@@ -701,7 +700,7 @@ test('fund a package throws on openUrl', t => {
   })
 })
 
-test('fund a package with type and multiple sources', t => {
+t.test('fund a package with type and multiple sources', t => {
   npm.prefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'foo',
@@ -719,7 +718,7 @@ test('fund a package with type and multiple sources', t => {
   })
 
   fund.exec(['.'], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.matchSnapshot(result, 'should print prompt select message')
 
     result = ''
@@ -727,7 +726,7 @@ test('fund a package with type and multiple sources', t => {
   })
 })
 
-test('fund colors', t => {
+t.test('fund colors', t => {
   npm.prefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'test-fund-colors',
@@ -783,7 +782,7 @@ test('fund colors', t => {
   npm.color = true
 
   fund.exec([], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.matchSnapshot(result, 'should print output with color info')
 
     result = ''
@@ -792,7 +791,7 @@ test('fund colors', t => {
   })
 })
 
-test('sub dep with fund info and a parent with no funding info', t => {
+t.test('sub dep with fund info and a parent with no funding info', t => {
   npm.prefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'test-multiple-funding-sources',
@@ -833,7 +832,7 @@ test('sub dep with fund info and a parent with no funding info', t => {
   })
 
   fund.exec([], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
     t.matchSnapshot(result, 'should nest sub dep as child of root')
 
     result = ''
diff --git a/test/lib/get.js b/test/lib/get.js
index a11597d2682db..9b77fbba3e6f4 100644
--- a/test/lib/get.js
+++ b/test/lib/get.js
@@ -1,8 +1,7 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 
-test('should retrieve values from npm.commands.config', (t) => {
-  const Get = requireInject('../../lib/get.js')
+t.test('should retrieve values from npm.commands.config', (t) => {
+  const Get = t.mock('../../lib/get.js')
   const get = new Get({
     commands: {
       config: ([action, arg]) => {
diff --git a/test/lib/help-search.js b/test/lib/help-search.js
index 567097a2eb183..845b3873e3cf9 100644
--- a/test/lib/help-search.js
+++ b/test/lib/help-search.js
@@ -1,6 +1,5 @@
-const { test } = require('tap')
+const t = require('tap')
 const { join } = require('path')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 const ansicolors = require('ansicolors')
 
@@ -43,12 +42,12 @@ const globDir = {
 const glob = (p, cb) =>
   cb(null, Object.keys(globDir).map((file) => join(globRoot, file)))
 
-const HelpSearch = requireInject('../../lib/help-search.js', {
+const HelpSearch = t.mock('../../lib/help-search.js', {
   glob,
 })
 const helpSearch = new HelpSearch(npm)
 
-test('npm help-search', t => {
+t.test('npm help-search', t => {
   globRoot = t.testdir(globDir)
   t.teardown(() => {
     OUTPUT.length = 0
@@ -64,7 +63,7 @@ test('npm help-search', t => {
   })
 })
 
-test('npm help-search multiple terms', t => {
+t.test('npm help-search multiple terms', t => {
   globRoot = t.testdir(globDir)
   t.teardown(() => {
     OUTPUT.length = 0
@@ -81,7 +80,7 @@ test('npm help-search multiple terms', t => {
   })
 })
 
-test('npm help-search long output', t => {
+t.test('npm help-search long output', t => {
   globRoot = t.testdir(globDir)
   config.long = true
   t.teardown(() => {
@@ -99,7 +98,7 @@ test('npm help-search long output', t => {
   })
 })
 
-test('npm help-search long output with color', t => {
+t.test('npm help-search long output with color', t => {
   globRoot = t.testdir(globDir)
   config.long = true
   npm.color = true
@@ -120,7 +119,7 @@ test('npm help-search long output with color', t => {
   })
 })
 
-test('npm help-search no args', t => {
+t.test('npm help-search no args', t => {
   return helpSearch.exec([], (err) => {
     t.notOk(err)
     t.match(OUTPUT, /npm help-search/, 'outputs usage')
@@ -128,7 +127,7 @@ test('npm help-search no args', t => {
   })
 })
 
-test('npm help-search no matches', t => {
+t.test('npm help-search no matches', t => {
   globRoot = t.testdir(globDir)
   t.teardown(() => {
     OUTPUT.length = 0
diff --git a/test/lib/help.js b/test/lib/help.js
index b5fe297b5c430..44ba5b1cabc3c 100644
--- a/test/lib/help.js
+++ b/test/lib/help.js
@@ -1,5 +1,4 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 const { EventEmitter } = require('events')
 
 const npmConfig = {
@@ -68,7 +67,7 @@ const openUrl = async (npm, url, msg) => {
   openUrlArg = url
 }
 
-const Help = requireInject('../../lib/help.js', {
+const Help = t.mock('../../lib/help.js', {
   '../../lib/utils/open-url.js': openUrl,
   child_process: {
     spawn,
@@ -77,7 +76,7 @@ const Help = requireInject('../../lib/help.js', {
 })
 const help = new Help(npm)
 
-test('npm help', t => {
+t.test('npm help', t => {
   return help.exec([], (err) => {
     if (err)
       throw err
@@ -87,7 +86,7 @@ test('npm help', t => {
   })
 })
 
-test('npm help completion', async t => {
+t.test('npm help completion', async t => {
   t.teardown(() => {
     globErr = null
   })
@@ -100,7 +99,7 @@ test('npm help completion', async t => {
   t.rejects(help.completion({ conf: { argv: { remain: [] } } }), /glob failed/, 'glob errors propagate')
 })
 
-test('npm help multiple args calls search', t => {
+t.test('npm help multiple args calls search', t => {
   t.teardown(() => {
     helpSearchArgs = null
   })
@@ -114,7 +113,7 @@ test('npm help multiple args calls search', t => {
   })
 })
 
-test('npm help no matches calls search', t => {
+t.test('npm help no matches calls search', t => {
   globResult = []
   t.teardown(() => {
     helpSearchArgs = null
@@ -130,7 +129,7 @@ test('npm help no matches calls search', t => {
   })
 })
 
-test('npm help glob errors propagate', t => {
+t.test('npm help glob errors propagate', t => {
   globErr = new Error('glob failed')
   t.teardown(() => {
     globErr = null
@@ -144,7 +143,7 @@ test('npm help glob errors propagate', t => {
   })
 })
 
-test('npm help whoami', t => {
+t.test('npm help whoami', t => {
   globResult = ['/root/man/man1/npm-whoami.1.xz']
   t.teardown(() => {
     globResult = globDefaults
@@ -162,7 +161,7 @@ test('npm help whoami', t => {
   })
 })
 
-test('npm help 1 install', t => {
+t.test('npm help 1 install', t => {
   npmConfig.viewer = 'browser'
   globResult = [
     '/root/man/man5/install.5',
@@ -185,7 +184,7 @@ test('npm help 1 install', t => {
   })
 })
 
-test('npm help 5 install', t => {
+t.test('npm help 5 install', t => {
   npmConfig.viewer = 'browser'
   globResult = [
     '/root/man/man5/install.5',
@@ -209,7 +208,7 @@ test('npm help 5 install', t => {
   })
 })
 
-test('npm help 7 config', t => {
+t.test('npm help 7 config', t => {
   npmConfig.viewer = 'browser'
   globResult = [
     '/root/man/man7/config.7',
@@ -232,7 +231,7 @@ test('npm help 7 config', t => {
   })
 })
 
-test('npm help package.json redirects to package-json', t => {
+t.test('npm help package.json redirects to package-json', t => {
   globResult = ['/root/man/man5/package-json.5']
   t.teardown(() => {
     globResult = globDefaults
@@ -251,7 +250,7 @@ test('npm help package.json redirects to package-json', t => {
   })
 })
 
-test('npm help ?(un)star', t => {
+t.test('npm help ?(un)star', t => {
   npmConfig.viewer = 'woman'
   globResult = [
     '/root/man/man1/npm-star.1',
@@ -274,7 +273,7 @@ test('npm help ?(un)star', t => {
   })
 })
 
-test('npm help - woman viewer propagates errors', t => {
+t.test('npm help - woman viewer propagates errors', t => {
   npmConfig.viewer = 'woman'
   spawnCode = 1
   globResult = [
@@ -297,7 +296,7 @@ test('npm help - woman viewer propagates errors', t => {
   })
 })
 
-test('npm help un*', t => {
+t.test('npm help un*', t => {
   globResult = [
     '/root/man/man1/npm-unstar.1',
     '/root/man/man1/npm-uninstall.1',
@@ -319,7 +318,7 @@ test('npm help un*', t => {
   })
 })
 
-test('npm help - man viewer propagates errors', t => {
+t.test('npm help - man viewer propagates errors', t => {
   spawnCode = 1
   globResult = [
     '/root/man/man1/npm-unstar.1',
@@ -341,7 +340,7 @@ test('npm help - man viewer propagates errors', t => {
   })
 })
 
-test('npm help with complex installation path finds proper help file', t => {
+t.test('npm help with complex installation path finds proper help file', t => {
   npmConfig.viewer = 'browser'
   globResult = [
     'C:/Program Files/node-v14.15.5-win-x64/node_modules/npm/man/man1/npm-install.1',
diff --git a/test/lib/hook.js b/test/lib/hook.js
index 3e012d94ee74f..2419f16041748 100644
--- a/test/lib/hook.js
+++ b/test/lib/hook.js
@@ -1,5 +1,4 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 
 const output = []
 const npm = {
@@ -55,20 +54,20 @@ const libnpmhook = {
   },
 }
 
-const Hook = requireInject('../../lib/hook.js', {
+const Hook = t.mock('../../lib/hook.js', {
   '../../lib/utils/otplease.js': async (opts, fn) => fn(opts),
   libnpmhook,
 })
 const hook = new Hook(npm)
 
-test('npm hook no args', t => {
+t.test('npm hook no args', t => {
   return hook.exec([], (err) => {
     t.match(err, /npm hook add/, 'throws usage with no arguments')
     t.end()
   })
 })
 
-test('npm hook add', t => {
+t.test('npm hook add', t => {
   t.teardown(() => {
     hookArgs = null
     output.length = 0
@@ -89,7 +88,7 @@ test('npm hook add', t => {
   })
 })
 
-test('npm hook add - unicode output', t => {
+t.test('npm hook add - unicode output', t => {
   npm.flatOptions.unicode = true
   t.teardown(() => {
     npm.flatOptions.unicode = false
@@ -112,7 +111,7 @@ test('npm hook add - unicode output', t => {
   })
 })
 
-test('npm hook add - json output', t => {
+t.test('npm hook add - json output', t => {
   npm.flatOptions.json = true
   t.teardown(() => {
     npm.flatOptions.json = false
@@ -140,7 +139,7 @@ test('npm hook add - json output', t => {
   })
 })
 
-test('npm hook add - parseable output', t => {
+t.test('npm hook add - parseable output', t => {
   npm.flatOptions.parseable = true
   t.teardown(() => {
     npm.flatOptions.parseable = false
@@ -168,7 +167,7 @@ test('npm hook add - parseable output', t => {
   })
 })
 
-test('npm hook add - silent output', t => {
+t.test('npm hook add - silent output', t => {
   npm.flatOptions.silent = true
   t.teardown(() => {
     npm.flatOptions.silent = false
@@ -191,7 +190,7 @@ test('npm hook add - silent output', t => {
   })
 })
 
-test('npm hook ls', t => {
+t.test('npm hook ls', t => {
   t.teardown(() => {
     hookArgs = null
     output.length = 0
@@ -214,7 +213,7 @@ test('npm hook ls', t => {
   })
 })
 
-test('npm hook ls, no results', t => {
+t.test('npm hook ls, no results', t => {
   hookResponse = []
   t.teardown(() => {
     hookResponse = null
@@ -235,7 +234,7 @@ test('npm hook ls, no results', t => {
   })
 })
 
-test('npm hook ls, single result', t => {
+t.test('npm hook ls, single result', t => {
   hookResponse = [{
     id: 1,
     name: 'semver',
@@ -264,7 +263,7 @@ test('npm hook ls, single result', t => {
   })
 })
 
-test('npm hook ls - json output', t => {
+t.test('npm hook ls - json output', t => {
   npm.flatOptions.json = true
   t.teardown(() => {
     npm.flatOptions.json = false
@@ -301,7 +300,7 @@ test('npm hook ls - json output', t => {
   })
 })
 
-test('npm hook ls - parseable output', t => {
+t.test('npm hook ls - parseable output', t => {
   npm.flatOptions.parseable = true
   t.teardown(() => {
     npm.flatOptions.parseable = false
@@ -327,7 +326,7 @@ test('npm hook ls - parseable output', t => {
   })
 })
 
-test('npm hook ls - silent output', t => {
+t.test('npm hook ls - silent output', t => {
   npm.flatOptions.silent = true
   t.teardown(() => {
     npm.flatOptions.silent = false
@@ -348,7 +347,7 @@ test('npm hook ls - silent output', t => {
   })
 })
 
-test('npm hook rm', t => {
+t.test('npm hook rm', t => {
   t.teardown(() => {
     hookArgs = null
     output.length = 0
@@ -369,7 +368,7 @@ test('npm hook rm', t => {
   })
 })
 
-test('npm hook rm - unicode output', t => {
+t.test('npm hook rm - unicode output', t => {
   npm.flatOptions.unicode = true
   t.teardown(() => {
     npm.flatOptions.unicode = false
@@ -392,7 +391,7 @@ test('npm hook rm - unicode output', t => {
   })
 })
 
-test('npm hook rm - silent output', t => {
+t.test('npm hook rm - silent output', t => {
   npm.flatOptions.silent = true
   t.teardown(() => {
     npm.flatOptions.silent = false
@@ -413,7 +412,7 @@ test('npm hook rm - silent output', t => {
   })
 })
 
-test('npm hook rm - json output', t => {
+t.test('npm hook rm - json output', t => {
   npm.flatOptions.json = true
   t.teardown(() => {
     npm.flatOptions.json = false
@@ -439,7 +438,7 @@ test('npm hook rm - json output', t => {
   })
 })
 
-test('npm hook rm - parseable output', t => {
+t.test('npm hook rm - parseable output', t => {
   npm.flatOptions.parseable = true
   t.teardown(() => {
     npm.flatOptions.parseable = false
@@ -463,7 +462,7 @@ test('npm hook rm - parseable output', t => {
   })
 })
 
-test('npm hook update', t => {
+t.test('npm hook update', t => {
   t.teardown(() => {
     hookArgs = null
     output.length = 0
@@ -486,7 +485,7 @@ test('npm hook update', t => {
   })
 })
 
-test('npm hook update - unicode', t => {
+t.test('npm hook update - unicode', t => {
   npm.flatOptions.unicode = true
   t.teardown(() => {
     npm.flatOptions.unicode = false
@@ -511,7 +510,7 @@ test('npm hook update - unicode', t => {
   })
 })
 
-test('npm hook update - json output', t => {
+t.test('npm hook update - json output', t => {
   npm.flatOptions.json = true
   t.teardown(() => {
     npm.flatOptions.json = false
@@ -539,7 +538,7 @@ test('npm hook update - json output', t => {
   })
 })
 
-test('npm hook update - parseable output', t => {
+t.test('npm hook update - parseable output', t => {
   npm.flatOptions.parseable = true
   t.teardown(() => {
     npm.flatOptions.parseable = false
@@ -565,7 +564,7 @@ test('npm hook update - parseable output', t => {
   })
 })
 
-test('npm hook update - silent output', t => {
+t.test('npm hook update - silent output', t => {
   npm.flatOptions.silent = true
   t.teardown(() => {
     npm.flatOptions.silent = false
diff --git a/test/lib/init.js b/test/lib/init.js
index 2b212f4a159e8..11273e4c392d4 100644
--- a/test/lib/init.js
+++ b/test/lib/init.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 
 let result = ''
@@ -26,20 +25,19 @@ const mocks = {
   'init-package-json': (dir, initFile, config, cb) => cb(null, 'data'),
   '../../lib/utils/usage.js': () => 'usage instructions',
 }
-const Init = requireInject('../../lib/init.js', mocks)
+const Init = t.mock('../../lib/init.js', mocks)
 const init = new Init(npm)
 
-t.afterEach(cb => {
+t.afterEach(() => {
   result = ''
   config.package = undefined
   npm.commands = {}
   npm.log = npmLog
-  cb()
 })
 
 t.test('classic npm init no args', t => {
   init.exec([], err => {
-    t.ifError(err, 'npm init no args')
+    t.error(err, 'npm init no args')
     t.matchSnapshot(result, 'should print helper info')
     t.end()
   })
@@ -62,7 +60,7 @@ t.test('classic npm init -y', t => {
     t.equal(msg, 'written successfully', 'should print done info')
   }
   init.exec([], err => {
-    t.ifError(err, 'npm init -y')
+    t.error(err, 'npm init -y')
     t.equal(result, '')
   })
 })
@@ -70,8 +68,8 @@ t.test('classic npm init -y', t => {
 t.test('npm init ', t => {
   t.plan(3)
   npm.commands.exec = (arr, cb) => {
-    t.deepEqual(config.package, [], 'should set empty array value')
-    t.deepEqual(
+    t.same(config.package, [], 'should set empty array value')
+    t.same(
       arr,
       ['create-react-app'],
       'should npx with listed packages'
@@ -79,14 +77,14 @@ t.test('npm init ', t => {
     cb()
   }
   init.exec(['react-app'], err => {
-    t.ifError(err, 'npm init react-app')
+    t.error(err, 'npm init react-app')
   })
 })
 
 t.test('npm init @scope/name', t => {
   t.plan(2)
   npm.commands.exec = (arr, cb) => {
-    t.deepEqual(
+    t.same(
       arr,
       ['@npmcli/create-something'],
       'should npx with scoped packages'
@@ -94,14 +92,14 @@ t.test('npm init @scope/name', t => {
     cb()
   }
   init.exec(['@npmcli/something'], err => {
-    t.ifError(err, 'npm init init @scope/name')
+    t.error(err, 'npm init init @scope/name')
   })
 })
 
 t.test('npm init git spec', t => {
   t.plan(2)
   npm.commands.exec = (arr, cb) => {
-    t.deepEqual(
+    t.same(
       arr,
       ['npm/create-something'],
       'should npx with git-spec packages'
@@ -109,14 +107,14 @@ t.test('npm init git spec', t => {
     cb()
   }
   init.exec(['npm/something'], err => {
-    t.ifError(err, 'npm init init @scope/name')
+    t.error(err, 'npm init init @scope/name')
   })
 })
 
 t.test('npm init @scope', t => {
   t.plan(2)
   npm.commands.exec = (arr, cb) => {
-    t.deepEqual(
+    t.same(
       arr,
       ['@npmcli/create'],
       'should npx with @scope/create pkgs'
@@ -124,7 +122,7 @@ t.test('npm init @scope', t => {
     cb()
   }
   init.exec(['@npmcli'], err => {
-    t.ifError(err, 'npm init init @scope/create')
+    t.error(err, 'npm init init @scope/create')
   })
 })
 
@@ -142,7 +140,7 @@ t.test('npm init tgz', t => {
 t.test('npm init @next', t => {
   t.plan(2)
   npm.commands.exec = (arr, cb) => {
-    t.deepEqual(
+    t.same(
       arr,
       ['create-something@next'],
       'should npx with something@next'
@@ -150,7 +148,7 @@ t.test('npm init @next', t => {
     cb()
   }
   init.exec(['something@next'], err => {
-    t.ifError(err, 'npm init init something@next')
+    t.error(err, 'npm init init something@next')
   })
 })
 
@@ -171,8 +169,8 @@ t.test('npm init exec error', t => {
 t.test('should not rewrite flatOptions', t => {
   t.plan(3)
   npm.commands.exec = (arr, cb) => {
-    t.deepEqual(config.package, [], 'should set empty array value')
-    t.deepEqual(
+    t.same(config.package, [], 'should set empty array value')
+    t.same(
       arr,
       ['create-react-app', 'my-app'],
       'should npx with extra args'
@@ -180,13 +178,13 @@ t.test('should not rewrite flatOptions', t => {
     cb()
   }
   init.exec(['react-app', 'my-app'], err => {
-    t.ifError(err, 'npm init react-app')
+    t.error(err, 'npm init react-app')
   })
 })
 
 t.test('npm init cancel', t => {
   t.plan(3)
-  const Init = requireInject('../../lib/init.js', {
+  const Init = t.mock('../../lib/init.js', {
     ...mocks,
     'init-package-json': (dir, initFile, config, cb) => cb(
       new Error('canceled')
@@ -199,12 +197,12 @@ t.test('npm init cancel', t => {
     t.equal(msg, 'canceled', 'should log canceled')
   }
   init.exec([], err => {
-    t.ifError(err, 'npm init cancel')
+    t.error(err, 'npm init cancel')
   })
 })
 
 t.test('npm init error', t => {
-  const Init = requireInject('../../lib/init.js', {
+  const Init = t.mock('../../lib/init.js', {
     ...mocks,
     'init-package-json': (dir, initFile, config, cb) => cb(
       new Error('Unknown Error')
diff --git a/test/lib/install-ci-test.js b/test/lib/install-ci-test.js
index 5f30efcabf259..2695e0f13decb 100644
--- a/test/lib/install-ci-test.js
+++ b/test/lib/install-ci-test.js
@@ -24,13 +24,12 @@ const installCITest = new InstallCITest({
 })
 
 t.test('the install-ci-test command', t => {
-  t.afterEach(cb => {
+  t.afterEach(() => {
     ciArgs = null
     ciCalled = false
     testArgs = null
     testCalled = false
     ciError = null
-    cb()
   })
 
   t.test('ci and test', t => {
diff --git a/test/lib/install-test.js b/test/lib/install-test.js
index 0c52bd5e3c012..adec91b619923 100644
--- a/test/lib/install-test.js
+++ b/test/lib/install-test.js
@@ -24,13 +24,12 @@ const installTest = new InstallTest({
 })
 
 t.test('the install-test command', t => {
-  t.afterEach(cb => {
+  t.afterEach(() => {
     installArgs = null
     installCalled = false
     testArgs = null
     testCalled = false
     installError = null
-    cb()
   })
 
   t.test('install and test', t => {
diff --git a/test/lib/install.js b/test/lib/install.js
index 619f0bb346984..b7929bddafdba 100644
--- a/test/lib/install.js
+++ b/test/lib/install.js
@@ -1,16 +1,15 @@
-const { test } = require('tap')
+const t = require('tap')
 
 const Install = require('../../lib/install.js')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 
-test('should install using Arborist', (t) => {
+t.test('should install using Arborist', (t) => {
   const SCRIPTS = []
   let ARB_ARGS = null
   let REIFY_CALLED = false
   let ARB_OBJ = null
 
-  const Install = requireInject('../../lib/install.js', {
+  const Install = t.mock('../../lib/install.js', {
     '@npmcli/run-script': ({ event }) => {
       SCRIPTS.push(event)
     },
@@ -73,10 +72,10 @@ test('should install using Arborist', (t) => {
   t.end()
 })
 
-test('should ignore scripts with --ignore-scripts', (t) => {
+t.test('should ignore scripts with --ignore-scripts', (t) => {
   const SCRIPTS = []
   let REIFY_CALLED = false
-  const Install = requireInject('../../lib/install.js', {
+  const Install = t.mock('../../lib/install.js', {
     '../../lib/utils/reify-finish.js': async () => {},
     '@npmcli/run-script': ({ event }) => {
       SCRIPTS.push(event)
@@ -106,8 +105,8 @@ test('should ignore scripts with --ignore-scripts', (t) => {
   })
 })
 
-test('should install globally using Arborist', (t) => {
-  const Install = requireInject('../../lib/install.js', {
+t.test('should install globally using Arborist', (t) => {
+  const Install = t.mock('../../lib/install.js', {
     '../../lib/utils/reify-finish.js': async () => {},
     '@npmcli/arborist': function () {
       this.reify = () => {}
@@ -127,8 +126,8 @@ test('should install globally using Arborist', (t) => {
   })
 })
 
-test('completion to folder', async t => {
-  const Install = requireInject('../../lib/install.js', {
+t.test('completion to folder', async t => {
+  const Install = t.mock('../../lib/install.js', {
     '../../lib/utils/reify-finish.js': async () => {},
     util: {
       promisify: (fn) => fn,
@@ -149,8 +148,8 @@ test('completion to folder', async t => {
   t.end()
 })
 
-test('completion to folder - invalid dir', async t => {
-  const Install = requireInject('../../lib/install.js', {
+t.test('completion to folder - invalid dir', async t => {
+  const Install = t.mock('../../lib/install.js', {
     '../../lib/utils/reify-finish.js': async () => {},
     util: {
       promisify: (fn) => fn,
@@ -167,8 +166,8 @@ test('completion to folder - invalid dir', async t => {
   t.end()
 })
 
-test('completion to folder - no matches', async t => {
-  const Install = requireInject('../../lib/install.js', {
+t.test('completion to folder - no matches', async t => {
+  const Install = t.mock('../../lib/install.js', {
     '../../lib/utils/reify-finish.js': async () => {},
     util: {
       promisify: (fn) => fn,
@@ -185,8 +184,8 @@ test('completion to folder - no matches', async t => {
   t.end()
 })
 
-test('completion to folder - match is not a package', async t => {
-  const Install = requireInject('../../lib/install.js', {
+t.test('completion to folder - match is not a package', async t => {
+  const Install = t.mock('../../lib/install.js', {
     '../../lib/utils/reify-finish.js': async () => {},
     util: {
       promisify: (fn) => fn,
@@ -206,14 +205,14 @@ test('completion to folder - match is not a package', async t => {
   t.end()
 })
 
-test('completion to url', async t => {
+t.test('completion to url', async t => {
   const install = new Install({})
   const res = await install.completion({ partialWord: 'http://path/to/url' })
   t.strictSame(res, [])
   t.end()
 })
 
-test('completion', async t => {
+t.test('completion', async t => {
   const install = new Install({})
   const res = await install.completion({ partialWord: 'toto' })
   t.notOk(res)
diff --git a/test/lib/link.js b/test/lib/link.js
index 0d96ba0bcd684..34c533fb72cd5 100644
--- a/test/lib/link.js
+++ b/test/lib/link.js
@@ -2,7 +2,6 @@ const { resolve } = require('path')
 
 const Arborist = require('@npmcli/arborist')
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 
 const redactCwd = (path) => {
@@ -40,7 +39,7 @@ const mocks = {
   '../../lib/utils/reify-output.js': () => reifyOutput(),
 }
 
-const Link = requireInject('../../lib/link.js', mocks)
+const Link = t.mock('../../lib/link.js', mocks)
 const link = new Link(npm)
 
 t.test('link to globalDir when in current working dir of pkg and no args', (t) => {
@@ -81,7 +80,7 @@ t.test('link to globalDir when in current working dir of pkg and no args', (t) =
   }
 
   link.exec([], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
   })
 })
 
@@ -189,7 +188,7 @@ t.test('link global linked pkg to local nm when using args', (t) => {
     'a',
     'file:../link-me-too',
   ], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
   })
 })
 
@@ -252,7 +251,7 @@ t.test('link pkg already in global space', (t) => {
   // - a: prev installed package available in globalDir
   // - file:./link-me-too: pkg that needs to be reified in globalDir first
   link.exec(['@myscope/linked'], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
   })
 })
 
@@ -310,7 +309,7 @@ t.test('link pkg already in global space when prefix is a symlink', (t) => {
   }
 
   link.exec(['@myscope/linked'], (err) => {
-    t.ifError(err, 'should not error out')
+    t.error(err, 'should not error out')
   })
 })
 
@@ -330,7 +329,7 @@ t.test('completion', async t => {
   npm.globalDir = resolve(testdir, 'global-prefix', 'lib', 'node_modules')
 
   const words = await link.completion({})
-  t.deepEqual(
+  t.same(
     words,
     ['bar', 'foo', 'ipsum', 'lorem'],
     'should list all package names available in globalDir'
diff --git a/test/lib/ll.js b/test/lib/ll.js
index 45eb4ec95b88f..28a3ab12c6a5f 100644
--- a/test/lib/ll.js
+++ b/test/lib/ll.js
@@ -1,4 +1,3 @@
-const requireInject = require('require-inject')
 const t = require('tap')
 
 t.test('ll', t => {
@@ -10,12 +9,12 @@ t.test('ll', t => {
     }
 
     exec (args, cb) {
-      t.deepEqual(args, ['pkg'], 'should forward args')
+      t.same(args, ['pkg'], 'should forward args')
       cb()
     }
   }
 
-  const LL = requireInject('../../lib/ll.js', {
+  const LL = t.mock('../../lib/ll.js', {
     '../../lib/ls.js': LS,
   })
   const ll = new LL({
diff --git a/test/lib/load-all-commands.js b/test/lib/load-all-commands.js
index cb3aefb1f8842..8267cd5437ec8 100644
--- a/test/lib/load-all-commands.js
+++ b/test/lib/load-all-commands.js
@@ -2,9 +2,8 @@
 // It does ensure that every command has a usage that renders, contains its
 // name, a description, and if it has completion it is a function.  That it
 // renders also ensures that any params we've defined in our commands work.
-const requireInject = require('require-inject')
-const npm = requireInject('../../lib/npm.js')
 const t = require('tap')
+const npm = t.mock('../../lib/npm.js')
 const { cmdList } = require('../../lib/utils/cmd-list.js')
 
 let npmOutput = []
@@ -20,8 +19,8 @@ t.test('load each command', t => {
       t.test(cmd, t => {
         const impl = npm.commands[cmd]
         if (impl.completion)
-          t.isa(impl.completion, 'function', 'completion, if present, is a function')
-        t.isa(impl, 'function', 'implementation is a function')
+          t.type(impl.completion, 'function', 'completion, if present, is a function')
+        t.type(impl, 'function', 'implementation is a function')
         t.ok(impl.description, 'implementation has a description')
         t.ok(impl.name, 'implementation has a name')
         t.match(impl.usage, cmd, 'usage contains the command')
diff --git a/test/lib/logout.js b/test/lib/logout.js
index bae797f969321..fb1e281b79ea4 100644
--- a/test/lib/logout.js
+++ b/test/lib/logout.js
@@ -1,6 +1,5 @@
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
-const { test } = require('tap')
+const t = require('tap')
 
 const config = {
   registry: 'https://registry.npmjs.org/',
@@ -24,10 +23,10 @@ const mocks = {
   'npm-registry-fetch': npmFetch,
 }
 
-const Logout = requireInject('../../lib/logout.js', mocks)
+const Logout = t.mock('../../lib/logout.js', mocks)
 const logout = new Logout(npm)
 
-test('token logout', async (t) => {
+t.test('token logout', async (t) => {
   t.plan(6)
 
   flatOptions.token = '@foo/'
@@ -55,9 +54,9 @@ test('token logout', async (t) => {
 
   await new Promise((res, rej) => {
     logout.exec([], (err) => {
-      t.ifError(err, 'should not error out')
+      t.error(err, 'should not error out')
 
-      t.deepEqual(
+      t.same(
         result,
         {
           url: '/-/user/token/%40foo%2F',
@@ -85,7 +84,7 @@ test('token logout', async (t) => {
   })
 })
 
-test('token scoped logout', async (t) => {
+t.test('token scoped logout', async (t) => {
   t.plan(8)
 
   flatOptions.token = '@foo/'
@@ -126,9 +125,9 @@ test('token scoped logout', async (t) => {
 
   await new Promise((res, rej) => {
     logout.exec([], (err) => {
-      t.ifError(err, 'should not error out')
+      t.error(err, 'should not error out')
 
-      t.deepEqual(
+      t.same(
         result,
         {
           url: '/-/user/token/%40foo%2F',
@@ -159,7 +158,7 @@ test('token scoped logout', async (t) => {
   })
 })
 
-test('user/pass logout', async (t) => {
+t.test('user/pass logout', async (t) => {
   t.plan(3)
 
   flatOptions.username = 'foo'
@@ -179,7 +178,7 @@ test('user/pass logout', async (t) => {
 
   await new Promise((res, rej) => {
     logout.exec([], (err) => {
-      t.ifError(err, 'should not error out')
+      t.error(err, 'should not error out')
 
       delete flatOptions.username
       delete flatOptions.password
@@ -192,7 +191,7 @@ test('user/pass logout', async (t) => {
   })
 })
 
-test('missing credentials', (t) => {
+t.test('missing credentials', (t) => {
   logout.exec([], (err) => {
     t.match(
       err.message,
@@ -204,7 +203,7 @@ test('missing credentials', (t) => {
   })
 })
 
-test('ignore invalid scoped registry config', async (t) => {
+t.test('ignore invalid scoped registry config', async (t) => {
   t.plan(5)
 
   flatOptions.token = '@foo/'
@@ -233,9 +232,9 @@ test('ignore invalid scoped registry config', async (t) => {
 
   await new Promise((res, rej) => {
     logout.exec([], (err) => {
-      t.ifError(err, 'should not error out')
+      t.error(err, 'should not error out')
 
-      t.deepEqual(
+      t.same(
         result,
         {
           url: '/-/user/token/%40foo%2F',
diff --git a/test/lib/ls.js b/test/lib/ls.js
index 5367dec688658..6eab0b05b8da9 100644
--- a/test/lib/ls.js
+++ b/test/lib/ls.js
@@ -1,3 +1,7 @@
+// TODO(isaacs): This test has a lot of very large objects pasted inline.
+// Consider using t.matchSnapshot on these instead, especially since many
+// of them contain the tap testdir folders, which are auto-generated and
+// may change when node-tap is updated.
 const t = require('tap')
 const mockNpm = require('../fixtures/mock-npm')
 
@@ -115,10 +119,7 @@ const redactCwd = res =>
 
 const jsonParse = res => JSON.parse(redactCwd(res))
 
-const cleanUpResult = (done, t) => {
-  result = ''
-  done()
-}
+const cleanUpResult = () => result = ''
 
 t.test('ls', (t) => {
   t.beforeEach(cleanUpResult)
@@ -137,7 +138,7 @@ t.test('ls', (t) => {
       ...simpleNmFixture,
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output tree representation of dependencies structure')
       t.end()
     })
@@ -173,7 +174,7 @@ t.test('ls', (t) => {
       t.equal(err.code, 'ELSPROBLEMS', 'should have error code')
       t.equal(
         redactCwd(err.message),
-        'extraneous: lorem@1.0.0 {CWD}/ls-ls-extraneous-deps/node_modules/lorem',
+        'extraneous: lorem@1.0.0 {CWD}/tap-testdir-ls-ls-extraneous-deps/node_modules/lorem',
         'should log extraneous dep as error'
       )
       t.matchSnapshot(redactCwd(result), 'should output containing problems info')
@@ -195,7 +196,7 @@ t.test('ls', (t) => {
       ...simpleNmFixture,
     })
     ls.exec(['lorem'], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurrences of filtered by package and colored output')
       npm.color = false
       t.end()
@@ -217,7 +218,7 @@ t.test('ls', (t) => {
       ...simpleNmFixture,
     })
     ls.exec(['.'], (err) => {
-      t.ifError(err, 'should not throw on missing dep above current level')
+      t.error(err, 'should not throw on missing dep above current level')
       t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurrences of filtered by package and colored output')
       config.all = true
       config.depth = Infinity
@@ -238,7 +239,7 @@ t.test('ls', (t) => {
       ...simpleNmFixture,
     })
     ls.exec(['bar'], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurrences of filtered package and its ancestors')
       t.end()
     })
@@ -266,7 +267,7 @@ t.test('ls', (t) => {
       },
     })
     ls.exec(['bar@*', 'lorem@1.0.0'], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurrences of multiple filtered packages and their ancestors')
       t.end()
     })
@@ -285,7 +286,7 @@ t.test('ls', (t) => {
       ...simpleNmFixture,
     })
     ls.exec(['notadep'], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output tree containing no dependencies info')
       t.equal(
         process.exitCode,
@@ -312,7 +313,7 @@ t.test('ls', (t) => {
       ...simpleNmFixture,
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output tree containing only top-level dependencies')
       config.all = true
       config.depth = Infinity
@@ -335,7 +336,7 @@ t.test('ls', (t) => {
       ...simpleNmFixture,
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output tree containing only top-level dependencies')
       config.all = true
       config.depth = Infinity
@@ -396,7 +397,7 @@ t.test('ls', (t) => {
       },
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output tree containing top-level deps and their deps only')
       config.all = true
       config.depth = Infinity
@@ -420,9 +421,9 @@ t.test('ls', (t) => {
       t.equal(err.code, 'ELSPROBLEMS', 'should have error code')
       t.equal(
         redactCwd(err.message).replace(/\r\n/g, '\n'),
-        'invalid: foo@1.0.0 {CWD}/ls-ls-missing-invalid-extraneous/node_modules/foo\n' +
+        'invalid: foo@1.0.0 {CWD}/tap-testdir-ls-ls-missing-invalid-extraneous/node_modules/foo\n' +
         'missing: ipsum@^1.0.0, required by test-npm-ls@1.0.0\n' +
-        'extraneous: lorem@1.0.0 {CWD}/ls-ls-missing-invalid-extraneous/node_modules/lorem',
+        'extraneous: lorem@1.0.0 {CWD}/tap-testdir-ls-ls-missing-invalid-extraneous/node_modules/lorem',
         'should log missing/invalid/extraneous errors'
       )
       t.matchSnapshot(redactCwd(result), 'should output tree containing missing, invalid, extraneous labels')
@@ -718,7 +719,7 @@ t.test('ls', (t) => {
   t.test('empty location', (t) => {
     npm.prefix = t.testdir({})
     ls.exec([], (err) => {
-      t.ifError(err, 'should not error out on empty locations')
+      t.error(err, 'should not error out on empty locations')
       t.matchSnapshot(redactCwd(result), 'should print empty result')
       t.end()
     })
@@ -898,7 +899,7 @@ t.test('ls', (t) => {
       },
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should print tree output containing deduped ref')
       t.end()
     })
@@ -936,7 +937,7 @@ t.test('ls', (t) => {
       },
     })
     ls.exec(['a'], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should print tree output containing deduped ref')
       npm.color = false
       t.end()
@@ -984,7 +985,7 @@ t.test('ls', (t) => {
       },
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should print tree output containing deduped ref')
       t.end()
     })
@@ -1033,7 +1034,7 @@ t.test('ls', (t) => {
       },
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should print tree output containing deduped ref')
       config.all = true
       config.depth = Infinity
@@ -1083,7 +1084,7 @@ t.test('ls', (t) => {
       },
     })
     ls.exec(['@npmcli/b'], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should print tree output containing deduped ref')
       npm.color = false
       t.end()
@@ -1131,7 +1132,7 @@ t.test('ls', (t) => {
       },
     })
     ls.exec(['@npmcli/c'], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should print tree output containing deduped ref')
       t.end()
     })
@@ -1221,7 +1222,7 @@ t.test('ls', (t) => {
     })
     touchHiddenPackageLock(npm.prefix)
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output tree containing git refs')
       t.end()
     })
@@ -1265,7 +1266,7 @@ t.test('ls', (t) => {
       }),
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should NOT print git refs in output tree')
       t.end()
     })
@@ -1453,12 +1454,12 @@ t.test('ls', (t) => {
     })
 
     ls.exec([], (err) => {
-      t.ifError(err, 'should NOT have ELSPROBLEMS error code')
+      t.error(err, 'should NOT have ELSPROBLEMS error code')
       t.matchSnapshot(redactCwd(result), 'should list workspaces properly')
 
       // should also be able to filter out one of the workspaces
       ls.exec(['a'], (err) => {
-        t.ifError(err, 'should NOT have ELSPROBLEMS error code when filter')
+        t.error(err, 'should NOT have ELSPROBLEMS error code when filter')
         t.matchSnapshot(redactCwd(result), 'should filter single workspace')
 
         t.end()
@@ -1516,17 +1517,17 @@ t.test('ls', (t) => {
 
     t.plan(6)
     ls.exec(['a'], (err) => {
-      t.ifError(err, 'should NOT have ELSPROBLEMS error code')
+      t.error(err, 'should NOT have ELSPROBLEMS error code')
       t.matchSnapshot(redactCwd(result), 'should list a in top-level only')
 
       ls.exec(['d'], (err) => {
-        t.ifError(err, 'should NOT have ELSPROBLEMS error code when filter')
+        t.error(err, 'should NOT have ELSPROBLEMS error code when filter')
         t.matchSnapshot(redactCwd(result), 'should print empty results msg')
 
         // if no --depth config is defined, should print path to dep
         config.depth = null // default config value
         ls.exec(['d'], (err) => {
-          t.ifError(err, 'should NOT have ELSPROBLEMS error code when filter')
+          t.error(err, 'should NOT have ELSPROBLEMS error code when filter')
           t.matchSnapshot(redactCwd(result), 'should print expected result')
         })
       })
@@ -1558,7 +1559,7 @@ t.test('ls --parseable', (t) => {
       ...simpleNmFixture,
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output parseable representation of dependencies structure')
       t.end()
     })
@@ -1610,7 +1611,7 @@ t.test('ls --parseable', (t) => {
       ...simpleNmFixture,
     })
     ls.exec(['lorem'], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurrences of filtered by package')
       t.end()
     })
@@ -1629,7 +1630,7 @@ t.test('ls --parseable', (t) => {
       ...simpleNmFixture,
     })
     ls.exec(['bar'], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurrences of filtered package')
       t.end()
     })
@@ -1657,7 +1658,7 @@ t.test('ls --parseable', (t) => {
       },
     })
     ls.exec(['bar@*', 'lorem@1.0.0'], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurrences of multiple filtered packages and their ancestors')
       t.end()
     })
@@ -1676,7 +1677,7 @@ t.test('ls --parseable', (t) => {
       ...simpleNmFixture,
     })
     ls.exec(['notadep'], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output parseable output containing no dependencies info')
       t.equal(
         process.exitCode,
@@ -1703,7 +1704,7 @@ t.test('ls --parseable', (t) => {
       ...simpleNmFixture,
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output parseable output containing only top-level dependencies')
       config.all = true
       config.depth = Infinity
@@ -1726,7 +1727,7 @@ t.test('ls --parseable', (t) => {
       ...simpleNmFixture,
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output tree containing only top-level dependencies')
       config.all = true
       config.depth = Infinity
@@ -1749,7 +1750,7 @@ t.test('ls --parseable', (t) => {
       ...simpleNmFixture,
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output parseable containing top-level deps and their deps only')
       config.all = true
       config.depth = Infinity
@@ -1973,7 +1974,7 @@ t.test('ls --parseable', (t) => {
     })
     ls.exec([], (err) => {
       t.equal(err.code, 'ELSPROBLEMS', 'should have error code')
-      t.match(redactCwd(err.message), 'extraneous: lorem@1.0.0 {CWD}/ls-ls-parseable--long-with-extraneous-deps/node_modules/lorem', 'should have error code')
+      t.match(redactCwd(err.message), 'extraneous: lorem@1.0.0 {CWD}/tap-testdir-ls-ls---parseable---long-with-extraneous-deps/node_modules/lorem', 'should have error code')
       t.matchSnapshot(redactCwd(result), 'should output long parseable output with extraneous info')
       t.end()
     })
@@ -2033,7 +2034,7 @@ t.test('ls --parseable', (t) => {
       },
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
+      t.error(err, 'npm ls')
       t.matchSnapshot(redactCwd(result), 'should output parseable results with symlink targets')
       config.long = false
       t.end()
@@ -2087,7 +2088,7 @@ t.test('ls --parseable', (t) => {
   t.test('empty location', (t) => {
     npm.prefix = t.testdir({})
     ls.exec([], (err) => {
-      t.ifError(err, 'should not error out on empty locations')
+      t.error(err, 'should not error out on empty locations')
       t.matchSnapshot(redactCwd(result), 'should print empty result')
       t.end()
     })
@@ -2382,8 +2383,8 @@ t.test('ls --json', (t) => {
       ...simpleNmFixture,
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
-      t.deepEqual(
+      t.error(err, 'npm ls')
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -2414,27 +2415,27 @@ t.test('ls --json', (t) => {
     })
     ls.exec([], (err) => {
       t.match(err, { code: 'ELSPROBLEMS' }, 'should list dep problems')
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           problems: [
-            'extraneous: bar@1.0.0 {CWD}/ls-ls-json-missing-package-json/node_modules/bar',
-            'extraneous: foo@1.0.0 {CWD}/ls-ls-json-missing-package-json/node_modules/foo',
-            'extraneous: lorem@1.0.0 {CWD}/ls-ls-json-missing-package-json/node_modules/lorem',
+            'extraneous: bar@1.0.0 {CWD}/tap-testdir-ls-ls---json-missing-package.json/node_modules/bar',
+            'extraneous: foo@1.0.0 {CWD}/tap-testdir-ls-ls---json-missing-package.json/node_modules/foo',
+            'extraneous: lorem@1.0.0 {CWD}/tap-testdir-ls-ls---json-missing-package.json/node_modules/lorem',
           ],
           dependencies: {
             bar: {
               version: '1.0.0',
               extraneous: true,
               problems: [
-                'extraneous: bar@1.0.0 {CWD}/ls-ls-json-missing-package-json/node_modules/bar',
+                'extraneous: bar@1.0.0 {CWD}/tap-testdir-ls-ls---json-missing-package.json/node_modules/bar',
               ],
             },
             foo: {
               version: '1.0.0',
               extraneous: true,
               problems: [
-                'extraneous: foo@1.0.0 {CWD}/ls-ls-json-missing-package-json/node_modules/foo',
+                'extraneous: foo@1.0.0 {CWD}/tap-testdir-ls-ls---json-missing-package.json/node_modules/foo',
               ],
               dependencies: {
                 bar: {
@@ -2446,7 +2447,7 @@ t.test('ls --json', (t) => {
               version: '1.0.0',
               extraneous: true,
               problems: [
-                'extraneous: lorem@1.0.0 {CWD}/ls-ls-json-missing-package-json/node_modules/lorem',
+                'extraneous: lorem@1.0.0 {CWD}/tap-testdir-ls-ls---json-missing-package.json/node_modules/lorem',
               ],
             },
           },
@@ -2471,7 +2472,7 @@ t.test('ls --json', (t) => {
     ls.exec([], (err) => {
       t.equal(
         redactCwd(err.message),
-        'extraneous: lorem@1.0.0 {CWD}/ls-ls-json-extraneous-deps/node_modules/lorem',
+        'extraneous: lorem@1.0.0 {CWD}/tap-testdir-ls-ls---json-extraneous-deps/node_modules/lorem',
         'should log extraneous dep as error'
       )
       t.equal(
@@ -2479,13 +2480,13 @@ t.test('ls --json', (t) => {
         'ELSPROBLEMS',
         'should have ELSPROBLEMS error code'
       )
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
           version: '1.0.0',
           problems: [
-            'extraneous: lorem@1.0.0 {CWD}/ls-ls-json-extraneous-deps/node_modules/lorem',
+            'extraneous: lorem@1.0.0 {CWD}/tap-testdir-ls-ls---json-extraneous-deps/node_modules/lorem',
           ],
           dependencies: {
             foo: {
@@ -2500,7 +2501,7 @@ t.test('ls --json', (t) => {
               version: '1.0.0',
               extraneous: true,
               problems: [
-                'extraneous: lorem@1.0.0 {CWD}/ls-ls-json-extraneous-deps/node_modules/lorem',
+                'extraneous: lorem@1.0.0 {CWD}/tap-testdir-ls-ls---json-extraneous-deps/node_modules/lorem',
               ],
             },
           },
@@ -2524,8 +2525,8 @@ t.test('ls --json', (t) => {
       ...simpleNmFixture,
     })
     ls.exec(['lorem'], (err) => {
-      t.ifError(err, 'npm ls')
-      t.deepEqual(
+      t.error(err, 'npm ls')
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -2560,8 +2561,8 @@ t.test('ls --json', (t) => {
       ...simpleNmFixture,
     })
     ls.exec(['bar'], (err) => {
-      t.ifError(err, 'npm ls')
-      t.deepEqual(
+      t.error(err, 'npm ls')
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -2605,8 +2606,8 @@ t.test('ls --json', (t) => {
       },
     })
     ls.exec(['bar@*', 'lorem@1.0.0'], (err) => {
-      t.ifError(err, 'npm ls')
-      t.deepEqual(
+      t.error(err, 'npm ls')
+      t.same(
         jsonParse(result),
         {
           version: '1.0.0',
@@ -2644,8 +2645,8 @@ t.test('ls --json', (t) => {
       ...simpleNmFixture,
     })
     ls.exec(['notadep'], (err) => {
-      t.ifError(err, 'npm ls')
-      t.deepEqual(
+      t.error(err, 'npm ls')
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -2678,8 +2679,8 @@ t.test('ls --json', (t) => {
       ...simpleNmFixture,
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
-      t.deepEqual(
+      t.error(err, 'npm ls')
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -2716,8 +2717,8 @@ t.test('ls --json', (t) => {
       ...simpleNmFixture,
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
-      t.deepEqual(
+      t.error(err, 'npm ls')
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -2754,8 +2755,8 @@ t.test('ls --json', (t) => {
       ...simpleNmFixture,
     })
     ls.exec([], (err) => {
-      t.ifError(err, 'npm ls')
-      t.deepEqual(
+      t.error(err, 'npm ls')
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -2796,22 +2797,22 @@ t.test('ls --json', (t) => {
     })
     ls.exec([], (err) => {
       t.match(err, { code: 'ELSPROBLEMS' }, 'should list dep problems')
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
           version: '1.0.0',
           problems: [
-            'invalid: foo@1.0.0 {CWD}/ls-ls-json-missing-invalid-extraneous/node_modules/foo',
+            'invalid: foo@1.0.0 {CWD}/tap-testdir-ls-ls---json-missing-invalid-extraneous/node_modules/foo',
             'missing: ipsum@^1.0.0, required by test-npm-ls@1.0.0',
-            'extraneous: lorem@1.0.0 {CWD}/ls-ls-json-missing-invalid-extraneous/node_modules/lorem',
+            'extraneous: lorem@1.0.0 {CWD}/tap-testdir-ls-ls---json-missing-invalid-extraneous/node_modules/lorem',
           ],
           dependencies: {
             foo: {
               version: '1.0.0',
               invalid: true,
               problems: [
-                'invalid: foo@1.0.0 {CWD}/ls-ls-json-missing-invalid-extraneous/node_modules/foo',
+                'invalid: foo@1.0.0 {CWD}/tap-testdir-ls-ls---json-missing-invalid-extraneous/node_modules/foo',
               ],
               dependencies: {
                 bar: {
@@ -2823,7 +2824,7 @@ t.test('ls --json', (t) => {
               version: '1.0.0',
               extraneous: true,
               problems: [
-                'extraneous: lorem@1.0.0 {CWD}/ls-ls-json-missing-invalid-extraneous/node_modules/lorem',
+                'extraneous: lorem@1.0.0 {CWD}/tap-testdir-ls-ls---json-missing-invalid-extraneous/node_modules/lorem',
               ],
             },
             ipsum: {
@@ -2864,7 +2865,7 @@ t.test('ls --json', (t) => {
       ...diffDepTypesNmFixture,
     })
     ls.exec([], () => {
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -2911,7 +2912,7 @@ t.test('ls --json', (t) => {
       ...diffDepTypesNmFixture,
     })
     ls.exec([], () => {
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -2968,7 +2969,7 @@ t.test('ls --json', (t) => {
       },
     })
     ls.exec([], () => {
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -3010,7 +3011,7 @@ t.test('ls --json', (t) => {
       ...diffDepTypesNmFixture,
     })
     ls.exec([], () => {
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -3051,7 +3052,7 @@ t.test('ls --json', (t) => {
       ...diffDepTypesNmFixture,
     })
     ls.exec([], () => {
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -3164,7 +3165,7 @@ t.test('ls --json', (t) => {
       }),
     })
     ls.exec([], () => {
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           version: '1.0.0',
@@ -3178,7 +3179,7 @@ t.test('ls --json', (t) => {
                   resolved: 'https://registry.npmjs.org/@isaacs/dedupe-tests-b/-/dedupe-tests-b-1.0.0.tgz',
                   extraneous: true,
                   problems: [
-                    'extraneous: @isaacs/dedupe-tests-b@ {CWD}/ls-ls-json-from-lockfile/node_modules/@isaacs/dedupe-tests-a/node_modules/@isaacs/dedupe-tests-b',
+                    'extraneous: @isaacs/dedupe-tests-b@ {CWD}/tap-testdir-ls-ls---json-from-lockfile/node_modules/@isaacs/dedupe-tests-a/node_modules/@isaacs/dedupe-tests-b',
                   ],
                 },
               },
@@ -3189,7 +3190,7 @@ t.test('ls --json', (t) => {
             },
           },
           problems: [
-            'extraneous: @isaacs/dedupe-tests-b@ {CWD}/ls-ls-json-from-lockfile/node_modules/@isaacs/dedupe-tests-a/node_modules/@isaacs/dedupe-tests-b',
+            'extraneous: @isaacs/dedupe-tests-b@ {CWD}/tap-testdir-ls-ls---json-from-lockfile/node_modules/@isaacs/dedupe-tests-a/node_modules/@isaacs/dedupe-tests-b',
           ],
         },
         'should output json containing only prod deps'
@@ -3221,7 +3222,7 @@ t.test('ls --json', (t) => {
       ...diffDepTypesNmFixture,
     })
     ls.exec([], () => {
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -3235,7 +3236,7 @@ t.test('ls --json', (t) => {
               devDependencies: {},
               peerDependencies: {},
               _dependencies: {},
-              path: '{CWD}/ls-ls-json--long/node_modules/peer-dep',
+              path: '{CWD}/tap-testdir-ls-ls---json---long/node_modules/peer-dep',
               extraneous: false,
             },
             'dev-dep': {
@@ -3254,7 +3255,7 @@ t.test('ls --json', (t) => {
                       devDependencies: {},
                       peerDependencies: {},
                       _dependencies: {},
-                      path: '{CWD}/ls-ls-json--long/node_modules/bar',
+                      path: '{CWD}/tap-testdir-ls-ls---json---long/node_modules/bar',
                       extraneous: false,
                     },
                   },
@@ -3262,7 +3263,7 @@ t.test('ls --json', (t) => {
                   devDependencies: {},
                   peerDependencies: {},
                   _dependencies: { bar: '^1.0.0' },
-                  path: '{CWD}/ls-ls-json--long/node_modules/foo',
+                  path: '{CWD}/tap-testdir-ls-ls---json---long/node_modules/foo',
                   extraneous: false,
                 },
               },
@@ -3270,7 +3271,7 @@ t.test('ls --json', (t) => {
               devDependencies: {},
               peerDependencies: {},
               _dependencies: { foo: '^1.0.0' },
-              path: '{CWD}/ls-ls-json--long/node_modules/dev-dep',
+              path: '{CWD}/tap-testdir-ls-ls---json---long/node_modules/dev-dep',
               extraneous: false,
             },
             lorem: {
@@ -3280,7 +3281,7 @@ t.test('ls --json', (t) => {
               devDependencies: {},
               peerDependencies: {},
               _dependencies: {},
-              path: '{CWD}/ls-ls-json--long/node_modules/lorem',
+              path: '{CWD}/tap-testdir-ls-ls---json---long/node_modules/lorem',
               extraneous: false,
             },
             'optional-dep': {
@@ -3291,7 +3292,7 @@ t.test('ls --json', (t) => {
               devDependencies: {},
               peerDependencies: {},
               _dependencies: {},
-              path: '{CWD}/ls-ls-json--long/node_modules/optional-dep',
+              path: '{CWD}/tap-testdir-ls-ls---json---long/node_modules/optional-dep',
               extraneous: false,
             },
             'prod-dep': {
@@ -3307,7 +3308,7 @@ t.test('ls --json', (t) => {
                   devDependencies: {},
                   peerDependencies: {},
                   _dependencies: {},
-                  path: '{CWD}/ls-ls-json--long/node_modules/prod-dep/node_modules/bar',
+                  path: '{CWD}/tap-testdir-ls-ls---json---long/node_modules/prod-dep/node_modules/bar',
                   extraneous: false,
                 },
               },
@@ -3315,7 +3316,7 @@ t.test('ls --json', (t) => {
               devDependencies: {},
               peerDependencies: {},
               _dependencies: { bar: '^2.0.0' },
-              path: '{CWD}/ls-ls-json--long/node_modules/prod-dep',
+              path: '{CWD}/tap-testdir-ls-ls---json---long/node_modules/prod-dep',
               extraneous: false,
             },
           },
@@ -3324,7 +3325,7 @@ t.test('ls --json', (t) => {
           peerDependencies: { 'peer-dep': '^1.0.0' },
           _id: 'test-npm-ls@1.0.0',
           _dependencies: { 'prod-dep': '^1.0.0', lorem: '^1.0.0', 'optional-dep': '^1.0.0' },
-          path: '{CWD}/ls-ls-json--long',
+          path: '{CWD}/tap-testdir-ls-ls---json---long',
           extraneous: false,
         },
         'should output long json info'
@@ -3359,7 +3360,7 @@ t.test('ls --json', (t) => {
       ...diffDepTypesNmFixture,
     })
     ls.exec([], () => {
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -3373,7 +3374,7 @@ t.test('ls --json', (t) => {
               devDependencies: {},
               peerDependencies: {},
               _dependencies: {},
-              path: '{CWD}/ls-ls-json--long-depth-0/node_modules/peer-dep',
+              path: '{CWD}/tap-testdir-ls-ls---json---long---depth-0/node_modules/peer-dep',
               extraneous: false,
             },
             'dev-dep': {
@@ -3384,7 +3385,7 @@ t.test('ls --json', (t) => {
               devDependencies: {},
               peerDependencies: {},
               _dependencies: { foo: '^1.0.0' },
-              path: '{CWD}/ls-ls-json--long-depth-0/node_modules/dev-dep',
+              path: '{CWD}/tap-testdir-ls-ls---json---long---depth-0/node_modules/dev-dep',
               extraneous: false,
             },
             lorem: {
@@ -3394,7 +3395,7 @@ t.test('ls --json', (t) => {
               devDependencies: {},
               peerDependencies: {},
               _dependencies: {},
-              path: '{CWD}/ls-ls-json--long-depth-0/node_modules/lorem',
+              path: '{CWD}/tap-testdir-ls-ls---json---long---depth-0/node_modules/lorem',
               extraneous: false,
             },
             'optional-dep': {
@@ -3405,7 +3406,7 @@ t.test('ls --json', (t) => {
               devDependencies: {},
               peerDependencies: {},
               _dependencies: {},
-              path: '{CWD}/ls-ls-json--long-depth-0/node_modules/optional-dep',
+              path: '{CWD}/tap-testdir-ls-ls---json---long---depth-0/node_modules/optional-dep',
               extraneous: false,
             },
             'prod-dep': {
@@ -3416,7 +3417,7 @@ t.test('ls --json', (t) => {
               devDependencies: {},
               peerDependencies: {},
               _dependencies: { bar: '^2.0.0' },
-              path: '{CWD}/ls-ls-json--long-depth-0/node_modules/prod-dep',
+              path: '{CWD}/tap-testdir-ls-ls---json---long---depth-0/node_modules/prod-dep',
               extraneous: false,
             },
           },
@@ -3425,7 +3426,7 @@ t.test('ls --json', (t) => {
           peerDependencies: { 'peer-dep': '^1.0.0' },
           _id: 'test-npm-ls@1.0.0',
           _dependencies: { 'prod-dep': '^1.0.0', lorem: '^1.0.0', 'optional-dep': '^1.0.0' },
-          path: '{CWD}/ls-ls-json--long-depth-0',
+          path: '{CWD}/tap-testdir-ls-ls---json---long---depth-0',
           extraneous: false,
         },
         'should output json containing top-level deps in long format'
@@ -3444,12 +3445,12 @@ t.test('ls --json', (t) => {
     ls.exec([], (err) => {
       t.match(err.message, 'Failed to parse root package.json', 'should have missin root package.json msg')
       t.match(err.code, 'EJSONPARSE', 'should have EJSONPARSE error code')
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           invalid: true,
           problems: [
-            'error in {CWD}/ls-ls-json-json-read-problems: Failed to parse root package.json',
+            'error in {CWD}/tap-testdir-ls-ls---json-json-read-problems: Failed to parse root package.json',
           ],
         },
         'should print empty json result'
@@ -3461,8 +3462,8 @@ t.test('ls --json', (t) => {
   t.test('empty location', (t) => {
     npm.prefix = t.testdir({})
     ls.exec([], (err) => {
-      t.ifError(err, 'should not error out on empty locations')
-      t.deepEqual(
+      t.error(err, 'should not error out on empty locations')
+      t.same(
         jsonParse(result),
         {},
         'should print empty json result'
@@ -3494,20 +3495,20 @@ t.test('ls --json', (t) => {
     })
     ls.exec([], (err) => {
       t.match(err.code, 'ELSPROBLEMS', 'Should have ELSPROBLEMS error code')
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
           version: '1.0.0',
           problems: [
-            'invalid: peer-dep@1.0.0 {CWD}/ls-ls-json-unmet-peer-dep/node_modules/peer-dep',
+            'invalid: peer-dep@1.0.0 {CWD}/tap-testdir-ls-ls---json-unmet-peer-dep/node_modules/peer-dep',
           ],
           dependencies: {
             'peer-dep': {
               version: '1.0.0',
               invalid: true,
               problems: [
-                'invalid: peer-dep@1.0.0 {CWD}/ls-ls-json-unmet-peer-dep/node_modules/peer-dep',
+                'invalid: peer-dep@1.0.0 {CWD}/tap-testdir-ls-ls---json-unmet-peer-dep/node_modules/peer-dep',
               ],
             },
             'dev-dep': {
@@ -3555,20 +3556,20 @@ t.test('ls --json', (t) => {
     ls.exec([], (err) => {
       t.match(err.code, 'ELSPROBLEMS', 'should have ELSPROBLEMS error code')
       t.match(err.message, /invalid: optional-dep@1.0.0/, 'should have invalid dep error msg')
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
           version: '1.0.0',
           problems: [
-            'invalid: optional-dep@1.0.0 {CWD}/ls-ls-json-unmet-optional-dep/node_modules/optional-dep', // mismatching optional deps get flagged in problems
+            'invalid: optional-dep@1.0.0 {CWD}/tap-testdir-ls-ls---json-unmet-optional-dep/node_modules/optional-dep', // mismatching optional deps get flagged in problems
           ],
           dependencies: {
             'optional-dep': {
               version: '1.0.0',
               invalid: true,
               problems: [
-                'invalid: optional-dep@1.0.0 {CWD}/ls-ls-json-unmet-optional-dep/node_modules/optional-dep',
+                'invalid: optional-dep@1.0.0 {CWD}/tap-testdir-ls-ls---json-unmet-optional-dep/node_modules/optional-dep',
               ],
             },
             'peer-dep': {
@@ -3625,7 +3626,7 @@ t.test('ls --json', (t) => {
       },
     })
     ls.exec([], () => {
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -3683,7 +3684,7 @@ t.test('ls --json', (t) => {
     })
     touchHiddenPackageLock(npm.prefix)
     ls.exec([], () => {
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -3743,7 +3744,7 @@ t.test('ls --json', (t) => {
     })
     touchHiddenPackageLock(npm.prefix)
     ls.exec([], () => {
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -3827,7 +3828,7 @@ t.test('ls --json', (t) => {
     })
     touchHiddenPackageLock(npm.prefix)
     ls.exec([], () => {
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           name: 'test-npm-ls',
@@ -3852,11 +3853,11 @@ t.test('ls --json', (t) => {
       }),
     })
     ls.exec([], () => {
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
           version: '1.0.0',
-          name: 'ls-ls-json-node-name-fallback-if-missing-root-package-name',
+          name: 'tap-testdir-ls-ls---json-node.name-fallback-if-missing-root-package-name',
         },
         'should use node.name as key in json result obj'
       )
@@ -3895,10 +3896,10 @@ t.test('ls --json', (t) => {
     npm.globalDir = resolve(fixtures, 'node_modules')
 
     ls.exec([], () => {
-      t.deepEqual(
+      t.same(
         jsonParse(result),
         {
-          name: 'ls-ls-json-global',
+          name: 'tap-testdir-ls-ls---json-global',
           dependencies: {
             a: {
               version: '1.0.0',
diff --git a/test/lib/npm.js b/test/lib/npm.js
index 4d40792af8f38..6f8f8936d3f73 100644
--- a/test/lib/npm.js
+++ b/test/lib/npm.js
@@ -174,34 +174,34 @@ t.test('npm.load', t => {
       t.equal(npm.log, npmlog, 'npmlog getter')
       t.equal(npm.lockfileVersion, 2, 'lockfileVersion getter')
       t.equal(npm.prefix, npm.localPrefix, 'prefix is local prefix')
-      t.notEqual(npm.prefix, npm.globalPrefix, 'prefix is not global prefix')
+      t.not(npm.prefix, npm.globalPrefix, 'prefix is not global prefix')
       npm.globalPrefix = npm.prefix
       t.equal(npm.prefix, npm.globalPrefix, 'globalPrefix setter')
       npm.localPrefix = dir + '/extra/prefix'
       t.equal(npm.prefix, npm.localPrefix, 'prefix is local prefix after localPrefix setter')
-      t.notEqual(npm.prefix, npm.globalPrefix, 'prefix is not global prefix after localPrefix setter')
+      t.not(npm.prefix, npm.globalPrefix, 'prefix is not global prefix after localPrefix setter')
 
       npm.prefix = dir + '/some/prefix'
       t.equal(npm.prefix, npm.localPrefix, 'prefix is local prefix after prefix setter')
-      t.notEqual(npm.prefix, npm.globalPrefix, 'prefix is not global prefix after prefix setter')
+      t.not(npm.prefix, npm.globalPrefix, 'prefix is not global prefix after prefix setter')
       t.equal(npm.bin, npm.localBin, 'bin is local bin after prefix setter')
-      t.notEqual(npm.bin, npm.globalBin, 'bin is not global bin after prefix setter')
+      t.not(npm.bin, npm.globalBin, 'bin is not global bin after prefix setter')
       t.equal(npm.dir, npm.localDir, 'dir is local dir after prefix setter')
-      t.notEqual(npm.dir, npm.globalDir, 'dir is not global dir after prefix setter')
+      t.not(npm.dir, npm.globalDir, 'dir is not global dir after prefix setter')
 
       npm.config.set('global', true)
       t.equal(npm.prefix, npm.globalPrefix, 'prefix is global prefix after setting global')
-      t.notEqual(npm.prefix, npm.localPrefix, 'prefix is not local prefix after setting global')
+      t.not(npm.prefix, npm.localPrefix, 'prefix is not local prefix after setting global')
       t.equal(npm.bin, npm.globalBin, 'bin is global bin after setting global')
-      t.notEqual(npm.bin, npm.localBin, 'bin is not local bin after setting global')
+      t.not(npm.bin, npm.localBin, 'bin is not local bin after setting global')
       t.equal(npm.dir, npm.globalDir, 'dir is global dir after setting global')
-      t.notEqual(npm.dir, npm.localDir, 'dir is not local dir after setting global')
+      t.not(npm.dir, npm.localDir, 'dir is not local dir after setting global')
 
       npm.prefix = dir + '/new/global/prefix'
       t.equal(npm.prefix, npm.globalPrefix, 'prefix is global prefix after prefix setter')
-      t.notEqual(npm.prefix, npm.localPrefix, 'prefix is not local prefix after prefix setter')
+      t.not(npm.prefix, npm.localPrefix, 'prefix is not local prefix after prefix setter')
       t.equal(npm.bin, npm.globalBin, 'bin is global bin after prefix setter')
-      t.notEqual(npm.bin, npm.localBin, 'bin is not local bin after prefix setter')
+      t.not(npm.bin, npm.localBin, 'bin is not local bin after prefix setter')
 
       beWindows()
       t.equal(npm.bin, npm.globalBin, 'bin is global bin in windows mode')
@@ -215,7 +215,7 @@ t.test('npm.load', t => {
 
     t.equal(npm.loaded, false, 'not loaded yet')
     t.equal(npm.loading, true, 'working on it tho')
-    t.isa(p, Promise, 'npm.load() returned a Promise first time')
+    t.type(p, Promise, 'npm.load() returned a Promise first time')
     t.equal(npm.load(second), undefined,
       'npm.load() returns nothing second time')
 
@@ -477,10 +477,7 @@ t.test('set process.title', t => {
     freshConfig()
   })
 
-  t.afterEach(cb => {
-    consoleLogs.length = 0
-    cb()
-  })
+  t.afterEach(() => consoleLogs.length = 0)
 
   t.test('basic title setting', async t => {
     freshConfig({
diff --git a/test/lib/org.js b/test/lib/org.js
index 4ffbf0af411a6..156232ac22a5d 100644
--- a/test/lib/org.js
+++ b/test/lib/org.js
@@ -1,5 +1,4 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 const ansiTrim = require('../../lib/utils/ansi-trim.js')
 
 const output = []
@@ -41,13 +40,13 @@ const libnpmorg = {
   },
 }
 
-const Org = requireInject('../../lib/org.js', {
+const Org = t.mock('../../lib/org.js', {
   '../../lib/utils/otplease.js': async (opts, fn) => fn(opts),
   libnpmorg,
 })
 const org = new Org(npm)
 
-test('completion', async t => {
+t.test('completion', async t => {
   const completion = (argv) =>
     org.completion({ conf: { argv: { remain: argv } } })
 
@@ -65,14 +64,14 @@ test('completion', async t => {
   t.rejects(completion(['npm', 'org', 'flurb']), /flurb not recognized/, 'errors for unknown subcommand')
 })
 
-test('npm org - invalid subcommand', t => {
+t.test('npm org - invalid subcommand', t => {
   org.exec(['foo'], (err) => {
     t.match(err, /npm org set/, 'prints usage information')
     t.end()
   })
 })
 
-test('npm org add', t => {
+t.test('npm org add', t => {
   t.teardown(() => {
     orgSetArgs = null
     output.length = 0
@@ -93,7 +92,7 @@ test('npm org add', t => {
   })
 })
 
-test('npm org add - no org', t => {
+t.test('npm org add - no org', t => {
   t.teardown(() => {
     orgSetArgs = null
     output.length = 0
@@ -105,7 +104,7 @@ test('npm org add - no org', t => {
   })
 })
 
-test('npm org add - no user', t => {
+t.test('npm org add - no user', t => {
   t.teardown(() => {
     orgSetArgs = null
     output.length = 0
@@ -117,7 +116,7 @@ test('npm org add - no user', t => {
   })
 })
 
-test('npm org add - invalid role', t => {
+t.test('npm org add - invalid role', t => {
   t.teardown(() => {
     orgSetArgs = null
     output.length = 0
@@ -129,7 +128,7 @@ test('npm org add - invalid role', t => {
   })
 })
 
-test('npm org add - more users', t => {
+t.test('npm org add - more users', t => {
   orgSize = 5
   t.teardown(() => {
     orgSize = 1
@@ -152,7 +151,7 @@ test('npm org add - more users', t => {
   })
 })
 
-test('npm org add - json output', t => {
+t.test('npm org add - json output', t => {
   npm.flatOptions.json = true
   t.teardown(() => {
     npm.flatOptions.json = false
@@ -182,7 +181,7 @@ test('npm org add - json output', t => {
   })
 })
 
-test('npm org add - parseable output', t => {
+t.test('npm org add - parseable output', t => {
   npm.flatOptions.parseable = true
   t.teardown(() => {
     npm.flatOptions.parseable = false
@@ -208,7 +207,7 @@ test('npm org add - parseable output', t => {
   })
 })
 
-test('npm org add - silent output', t => {
+t.test('npm org add - silent output', t => {
   npm.flatOptions.silent = true
   t.teardown(() => {
     npm.flatOptions.silent = false
@@ -231,7 +230,7 @@ test('npm org add - silent output', t => {
   })
 })
 
-test('npm org rm', t => {
+t.test('npm org rm', t => {
   t.teardown(() => {
     orgRmArgs = null
     orgLsArgs = null
@@ -256,7 +255,7 @@ test('npm org rm', t => {
   })
 })
 
-test('npm org rm - no org', t => {
+t.test('npm org rm - no org', t => {
   t.teardown(() => {
     orgRmArgs = null
     orgLsArgs = null
@@ -269,7 +268,7 @@ test('npm org rm - no org', t => {
   })
 })
 
-test('npm org rm - no user', t => {
+t.test('npm org rm - no user', t => {
   t.teardown(() => {
     orgRmArgs = null
     orgLsArgs = null
@@ -282,7 +281,7 @@ test('npm org rm - no user', t => {
   })
 })
 
-test('npm org rm - one user left', t => {
+t.test('npm org rm - one user left', t => {
   orgList = {
     one: 'developer',
   }
@@ -312,7 +311,7 @@ test('npm org rm - one user left', t => {
   })
 })
 
-test('npm org rm - json output', t => {
+t.test('npm org rm - json output', t => {
   npm.flatOptions.json = true
   t.teardown(() => {
     npm.flatOptions.json = false
@@ -344,7 +343,7 @@ test('npm org rm - json output', t => {
   })
 })
 
-test('npm org rm - parseable output', t => {
+t.test('npm org rm - parseable output', t => {
   npm.flatOptions.parseable = true
   t.teardown(() => {
     npm.flatOptions.parseable = false
@@ -374,7 +373,7 @@ test('npm org rm - parseable output', t => {
   })
 })
 
-test('npm org rm - silent output', t => {
+t.test('npm org rm - silent output', t => {
   npm.flatOptions.silent = true
   t.teardown(() => {
     npm.flatOptions.silent = false
@@ -401,7 +400,7 @@ test('npm org rm - silent output', t => {
   })
 })
 
-test('npm org ls', t => {
+t.test('npm org ls', t => {
   orgList = {
     one: 'developer',
     two: 'admin',
@@ -429,7 +428,7 @@ test('npm org ls', t => {
   })
 })
 
-test('npm org ls - user filter', t => {
+t.test('npm org ls - user filter', t => {
   orgList = {
     username: 'admin',
     missing: 'admin',
@@ -455,7 +454,7 @@ test('npm org ls - user filter', t => {
   })
 })
 
-test('npm org ls - user filter, missing user', t => {
+t.test('npm org ls - user filter, missing user', t => {
   orgList = {
     missing: 'admin',
   }
@@ -480,7 +479,7 @@ test('npm org ls - user filter, missing user', t => {
   })
 })
 
-test('npm org ls - no org', t => {
+t.test('npm org ls - no org', t => {
   t.teardown(() => {
     orgLsArgs = null
     output.length = 0
@@ -492,7 +491,7 @@ test('npm org ls - no org', t => {
   })
 })
 
-test('npm org ls - json output', t => {
+t.test('npm org ls - json output', t => {
   npm.flatOptions.json = true
   orgList = {
     one: 'developer',
@@ -519,7 +518,7 @@ test('npm org ls - json output', t => {
   })
 })
 
-test('npm org ls - parseable output', t => {
+t.test('npm org ls - parseable output', t => {
   npm.flatOptions.parseable = true
   orgList = {
     one: 'developer',
@@ -551,7 +550,7 @@ test('npm org ls - parseable output', t => {
   })
 })
 
-test('npm org ls - silent output', t => {
+t.test('npm org ls - silent output', t => {
   npm.flatOptions.silent = true
   orgList = {
     one: 'developer',
diff --git a/test/lib/outdated.js b/test/lib/outdated.js
index 5aff7c37ac11a..605853056a000 100644
--- a/test/lib/outdated.js
+++ b/test/lib/outdated.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 
 const packument = spec => {
@@ -85,7 +84,7 @@ const globalDir = t.testdir({
 })
 
 const outdated = (dir, opts) => {
-  const Outdated = requireInject('../../lib/outdated.js', {
+  const Outdated = t.mock('../../lib/outdated.js', {
     pacote: {
       packument,
     },
@@ -99,10 +98,7 @@ const outdated = (dir, opts) => {
   return new Outdated(npm)
 }
 
-t.beforeEach((done) => {
-  logs = ''
-  done()
-})
+t.beforeEach(() => logs = '')
 
 const redactCwd = (path) => {
   const normalizePath = p => p
@@ -342,7 +338,7 @@ t.test('should return if no outdated deps', t => {
   outdated(testDir, {
     global: false,
   }).exec([], () => {
-    t.equals(logs.length, 0, 'no logs')
+    t.equal(logs.length, 0, 'no logs')
     t.end()
   })
 })
@@ -369,7 +365,7 @@ t.test('throws if error with a dep', t => {
   outdated(testDir, {
     global: false,
   }).exec([], (err) => {
-    t.equals(err.message, 'There is an error with this package.')
+    t.equal(err.message, 'There is an error with this package.')
     t.end()
   })
 })
@@ -389,7 +385,7 @@ t.test('should skip missing non-prod deps', t => {
   outdated(testDir, {
     global: false,
   }).exec([], () => {
-    t.equals(logs.length, 0, 'no logs')
+    t.equal(logs.length, 0, 'no logs')
     t.end()
   })
 })
@@ -414,7 +410,7 @@ t.test('should skip invalid pkg ranges', t => {
   })
 
   outdated(testDir, {}).exec([], () => {
-    t.equals(logs.length, 0, 'no logs')
+    t.equal(logs.length, 0, 'no logs')
     t.end()
   })
 })
@@ -439,7 +435,7 @@ t.test('should skip git specs', t => {
   })
 
   outdated(testDir, {}).exec([], () => {
-    t.equals(logs.length, 0, 'no logs')
+    t.equal(logs.length, 0, 'no logs')
     t.end()
   })
 })
diff --git a/test/lib/owner.js b/test/lib/owner.js
index 11aeacb7be710..4af8d1ebbb8fa 100644
--- a/test/lib/owner.js
+++ b/test/lib/owner.js
@@ -1,4 +1,3 @@
-const requireInject = require('require-inject')
 const t = require('tap')
 
 let result = ''
@@ -32,7 +31,7 @@ const npmcliMaintainers = [
   { email: 'i@izs.me', name: 'isaacs' },
 ]
 
-const Owner = requireInject('../../lib/owner.js', mocks)
+const Owner = t.mock('../../lib/owner.js', mocks)
 const owner = new Owner(npm)
 
 t.test('owner no args', t => {
@@ -72,7 +71,7 @@ t.test('owner ls no args', t => {
   })
 
   owner.exec(['ls'], err => {
-    t.ifError(err, 'npm owner ls no args')
+    t.error(err, 'npm owner ls no args')
     t.matchSnapshot(result, 'should output owners of cwd package')
   })
 })
@@ -140,7 +139,7 @@ t.test('owner ls ', t => {
   })
 
   owner.exec(['ls', '@npmcli/map-workspaces'], err => {
-    t.ifError(err, 'npm owner ls ')
+    t.error(err, 'npm owner ls ')
     t.matchSnapshot(result, 'should output owners of ')
   })
 })
@@ -156,7 +155,7 @@ t.test('owner ls  no maintainers', t => {
   })
 
   owner.exec(['ls', '@npmcli/map-workspaces'], err => {
-    t.ifError(err, 'npm owner ls  no maintainers')
+    t.error(err, 'npm owner ls  no maintainers')
     t.equal(result, 'no admin found', 'should output no admint found msg')
     t.end()
   })
@@ -190,7 +189,7 @@ t.test('owner add  ', t => {
           name: '@npmcli/map-workspaces',
         },
       }, 'should use expected opts')
-      t.deepEqual(
+      t.same(
         opts.body.maintainers,
         [
           ...npmcliMaintainers,
@@ -227,7 +226,7 @@ t.test('owner add  ', t => {
   })
 
   owner.exec(['add', 'foo', '@npmcli/map-workspaces'], err => {
-    t.ifError(err, 'npm owner add  ')
+    t.error(err, 'npm owner add  ')
     t.equal(result, '+ foo (@npmcli/map-workspaces)', 'should output add result')
   })
 })
@@ -260,7 +259,7 @@ t.test('owner add  cwd package', t => {
   })
 
   owner.exec(['add', 'foo'], err => {
-    t.ifError(err, 'npm owner add  cwd package')
+    t.error(err, 'npm owner add  cwd package')
     t.equal(result, '+ foo (@npmcli/map-workspaces)', 'should output add result')
     t.end()
   })
@@ -303,7 +302,7 @@ t.test('owner add   already an owner', t => {
   })
 
   owner.exec(['add', 'ruyadorno', '@npmcli/map-workspaces'], err => {
-    t.ifError(err, 'npm owner add   already an owner')
+    t.error(err, 'npm owner add   already an owner')
   })
 })
 
@@ -448,7 +447,7 @@ t.test('owner add   no previous maintainers property from server', t
   })
 
   owner.exec(['add', 'foo', '@npmcli/no-owners-pkg'], err => {
-    t.ifError(err, 'npm owner add  ')
+    t.error(err, 'npm owner add  ')
     t.equal(result, '+ foo (@npmcli/no-owners-pkg)', 'should output add result')
     t.end()
   })
@@ -505,7 +504,7 @@ t.test('owner rm  ', t => {
           name: '@npmcli/map-workspaces',
         },
       }, 'should use expected opts')
-      t.deepEqual(
+      t.same(
         opts.body.maintainers,
         npmcliMaintainers.filter(m => m.name !== 'ruyadorno'),
         'should contain expected new owners, removing requested user'
@@ -536,7 +535,7 @@ t.test('owner rm  ', t => {
   })
 
   owner.exec(['rm', 'ruyadorno', '@npmcli/map-workspaces'], err => {
-    t.ifError(err, 'npm owner rm  ')
+    t.error(err, 'npm owner rm  ')
     t.equal(result, '- ruyadorno (@npmcli/map-workspaces)', 'should output rm result')
   })
 })
@@ -576,7 +575,7 @@ t.test('owner rm   not a current owner', t => {
   })
 
   owner.exec(['rm', 'foo', '@npmcli/map-workspaces'], err => {
-    t.ifError(err, 'npm owner rm   not a current owner')
+    t.error(err, 'npm owner rm   not a current owner')
   })
 })
 
@@ -608,7 +607,7 @@ t.test('owner rm  cwd package', t => {
   })
 
   owner.exec(['rm', 'ruyadorno'], err => {
-    t.ifError(err, 'npm owner rm  cwd package')
+    t.error(err, 'npm owner rm  cwd package')
     t.equal(result, '- ruyadorno (@npmcli/map-workspaces)', 'should output rm result')
     t.end()
   })
diff --git a/test/lib/pack.js b/test/lib/pack.js
index 4bcfe8ae3fd9c..64f4d1258b9ce 100644
--- a/test/lib/pack.js
+++ b/test/lib/pack.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 const pacote = require('pacote')
 
@@ -23,13 +22,10 @@ const mockPacote = {
   },
 }
 
-t.afterEach(cb => {
-  OUTPUT.length = 0
-  cb()
-})
+t.afterEach(() => OUTPUT.length = 0)
 
 t.test('should pack current directory with no arguments', (t) => {
-  const Pack = requireInject('../../lib/pack.js', {
+  const Pack = t.mock('../../lib/pack.js', {
     libnpmpack,
     npmlog: {
       notice: () => {},
@@ -65,7 +61,7 @@ t.test('should pack given directory', (t) => {
     }, null, 2),
   })
 
-  const Pack = requireInject('../../lib/pack.js', {
+  const Pack = t.mock('../../lib/pack.js', {
     libnpmpack,
     npmlog: {
       notice: () => {},
@@ -101,7 +97,7 @@ t.test('should pack given directory for scoped package', (t) => {
     }, null, 2),
   })
 
-  const Pack = requireInject('../../lib/pack.js', {
+  const Pack = t.mock('../../lib/pack.js', {
     libnpmpack,
     npmlog: {
       notice: () => {},
@@ -130,7 +126,7 @@ t.test('should pack given directory for scoped package', (t) => {
 })
 
 t.test('should log pack contents', (t) => {
-  const Pack = requireInject('../../lib/pack.js', {
+  const Pack = t.mock('../../lib/pack.js', {
     '../../lib/utils/tar.js': {
       ...require('../../lib/utils/tar.js'),
       logTar: () => {
@@ -184,7 +180,7 @@ t.test('workspaces', (t) => {
       }),
     },
   })
-  const Pack = requireInject('../../lib/pack.js', {
+  const Pack = t.mock('../../lib/pack.js', {
     libnpmpack,
     pacote: mockPacote,
     npmlog: {
diff --git a/test/lib/ping.js b/test/lib/ping.js
index 95361035acb53..c2d53efef5a7e 100644
--- a/test/lib/ping.js
+++ b/test/lib/ping.js
@@ -1,13 +1,12 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 const mockNpm = require('../fixtures/mock-npm')
 
-test('pings', (t) => {
+t.test('pings', (t) => {
   t.plan(8)
 
   const registry = 'https://registry.npmjs.org'
   let noticeCalls = 0
-  const Ping = requireInject('../../lib/ping.js', {
+  const Ping = t.mock('../../lib/ping.js', {
     '../../lib/utils/ping.js': function (spec) {
       t.equal(spec.registry, registry, 'passes flatOptions')
       return {}
@@ -33,18 +32,18 @@ test('pings', (t) => {
 
   ping.exec([], (err) => {
     t.equal(noticeCalls, 2, 'should have logged 2 lines')
-    t.ifError(err, 'npm ping')
+    t.error(err, 'npm ping')
     t.ok('should be able to ping')
   })
 })
 
-test('pings and logs details', (t) => {
+t.test('pings and logs details', (t) => {
   t.plan(10)
 
   const registry = 'https://registry.npmjs.org'
   const details = { extra: 'data' }
   let noticeCalls = 0
-  const Ping = requireInject('../../lib/ping.js', {
+  const Ping = t.mock('../../lib/ping.js', {
     '../../lib/utils/ping.js': function (spec) {
       t.equal(spec.registry, registry, 'passes flatOptions')
       return details
@@ -74,18 +73,18 @@ test('pings and logs details', (t) => {
 
   ping.exec([], (err) => {
     t.equal(noticeCalls, 3, 'should have logged 3 lines')
-    t.ifError(err, 'npm ping')
+    t.error(err, 'npm ping')
     t.ok('should be able to ping')
   })
 })
 
-test('pings and returns json', (t) => {
+t.test('pings and returns json', (t) => {
   t.plan(11)
 
   const registry = 'https://registry.npmjs.org'
   const details = { extra: 'data' }
   let noticeCalls = 0
-  const Ping = requireInject('../../lib/ping.js', {
+  const Ping = t.mock('../../lib/ping.js', {
     '../../lib/utils/ping.js': function (spec) {
       t.equal(spec.registry, registry, 'passes flatOptions')
       return details
@@ -117,7 +116,7 @@ test('pings and returns json', (t) => {
 
   ping.exec([], (err) => {
     t.equal(noticeCalls, 2, 'should have logged 2 lines')
-    t.ifError(err, 'npm ping')
+    t.error(err, 'npm ping')
     t.ok('should be able to ping')
   })
 })
diff --git a/test/lib/prefix.js b/test/lib/prefix.js
index 5eb7ddb934d93..526631388e74f 100644
--- a/test/lib/prefix.js
+++ b/test/lib/prefix.js
@@ -13,7 +13,7 @@ t.test('prefix', (t) => {
   })
 
   prefix.exec([], (err) => {
-    t.ifError(err, 'npm prefix')
+    t.error(err, 'npm prefix')
     t.ok('should have printed directory')
   })
 })
diff --git a/test/lib/profile.js b/test/lib/profile.js
index 5b1210615aa2f..17bcf99b9b653 100644
--- a/test/lib/profile.js
+++ b/test/lib/profile.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 
 let result = ''
@@ -67,16 +66,15 @@ const userProfile = {
   github: 'https://github.com/npm',
 }
 
-t.afterEach(cb => {
+t.afterEach(() => {
   result = ''
   flatOptions.otp = ''
   config.json = false
   config.parseable = false
   config.registry = 'https://registry.npmjs.org/'
-  cb()
 })
 
-const Profile = requireInject('../../lib/profile.js', mocks)
+const Profile = t.mock('../../lib/profile.js', mocks)
 const profile = new Profile(npm)
 
 t.test('no args', t => {
@@ -97,7 +95,7 @@ t.test('profile get no args', t => {
     },
   }
 
-  const Profile = requireInject('../../lib/profile.js', {
+  const Profile = t.mock('../../lib/profile.js', {
     ...mocks,
     'npm-profile': npmProfile,
   })
@@ -123,7 +121,7 @@ t.test('profile get no args', t => {
       if (err)
         throw err
 
-      t.deepEqual(
+      t.same(
         JSON.parse(result),
         userProfile,
         'should output json profile result'
@@ -157,7 +155,7 @@ t.test('profile get no args', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
     })
@@ -185,7 +183,7 @@ t.test('profile get no args', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
     })
@@ -213,7 +211,7 @@ t.test('profile get no args', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
     })
@@ -241,7 +239,7 @@ t.test('profile get ', t => {
     },
   }
 
-  const Profile = requireInject('../../lib/profile.js', {
+  const Profile = t.mock('../../lib/profile.js', {
     ...mocks,
     'npm-profile': npmProfile,
   })
@@ -268,7 +266,7 @@ t.test('profile get ', t => {
       if (err)
         throw err
 
-      t.deepEqual(
+      t.same(
         JSON.parse(result),
         userProfile,
         'should output json profile result ignoring args filter'
@@ -302,7 +300,7 @@ t.test('profile get multiple args', t => {
     },
   }
 
-  const Profile = requireInject('../../lib/profile.js', {
+  const Profile = t.mock('../../lib/profile.js', {
     ...mocks,
     'npm-profile': npmProfile,
   })
@@ -328,7 +326,7 @@ t.test('profile get multiple args', t => {
       if (err)
         throw err
 
-      t.deepEqual(
+      t.same(
         JSON.parse(result),
         userProfile,
         'should output json profile result and ignore args'
@@ -436,7 +434,7 @@ t.test('profile set  ', t => {
     t.test('default output', t => {
       t.plan(2)
 
-      const Profile = requireInject('../../lib/profile.js', {
+      const Profile = t.mock('../../lib/profile.js', {
         ...mocks,
         'npm-profile': npmProfile(t),
       })
@@ -459,7 +457,7 @@ t.test('profile set  ', t => {
 
       config.json = true
 
-      const Profile = requireInject('../../lib/profile.js', {
+      const Profile = t.mock('../../lib/profile.js', {
         ...mocks,
         'npm-profile': npmProfile(t),
       })
@@ -469,7 +467,7 @@ t.test('profile set  ', t => {
         if (err)
           throw err
 
-        t.deepEqual(
+        t.same(
           JSON.parse(result),
           {
             fullname: 'Lorem Ipsum',
@@ -484,7 +482,7 @@ t.test('profile set  ', t => {
 
       config.parseable = true
 
-      const Profile = requireInject('../../lib/profile.js', {
+      const Profile = t.mock('../../lib/profile.js', {
         ...mocks,
         'npm-profile': npmProfile(t),
       })
@@ -531,7 +529,7 @@ t.test('profile set  ', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
     })
@@ -595,7 +593,7 @@ t.test('profile set  ', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
       '../../lib/utils/read-user-info.js': readUserInfo,
@@ -663,7 +661,7 @@ t.test('profile set  ', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       npmlog,
       'npm-profile': npmProfile,
@@ -754,7 +752,7 @@ t.test('enable-2fa', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
     })
@@ -783,7 +781,7 @@ t.test('enable-2fa', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
     })
@@ -804,7 +802,7 @@ t.test('enable-2fa', t => {
   t.test('no auth found', t => {
     npm.config.getCredentialsByURI = () => ({})
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
     })
     const profile = new Profile(npm)
@@ -883,7 +881,7 @@ t.test('enable-2fa', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
       '../../lib/utils/read-user-info.js': readUserInfo,
@@ -985,7 +983,7 @@ t.test('enable-2fa', t => {
       generate: (url, cb) => cb('qrcode'),
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
       'qrcode-terminal': qrcode,
@@ -1037,7 +1035,7 @@ t.test('enable-2fa', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
       '../../lib/utils/read-user-info.js': readUserInfo,
@@ -1083,7 +1081,7 @@ t.test('enable-2fa', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
       '../../lib/utils/read-user-info.js': readUserInfo,
@@ -1132,7 +1130,7 @@ t.test('enable-2fa', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
       '../../lib/utils/read-user-info.js': readUserInfo,
@@ -1181,7 +1179,7 @@ t.test('enable-2fa', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
       '../../lib/utils/read-user-info.js': readUserInfo,
@@ -1215,7 +1213,7 @@ t.test('disable-2fa', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
     })
@@ -1240,7 +1238,7 @@ t.test('disable-2fa', t => {
         return userProfile
       },
       async set (newProfile, conf) {
-        t.deepEqual(
+        t.same(
           newProfile,
           {
             tfa: {
@@ -1277,7 +1275,7 @@ t.test('disable-2fa', t => {
     })
 
     t.test('default output', t => {
-      const Profile = requireInject('../../lib/profile.js', {
+      const Profile = t.mock('../../lib/profile.js', {
         ...mocks,
         'npm-profile': npmProfile(t),
         '../../lib/utils/read-user-info.js': readUserInfo(t),
@@ -1300,7 +1298,7 @@ t.test('disable-2fa', t => {
     t.test('--json', t => {
       config.json = true
 
-      const Profile = requireInject('../../lib/profile.js', {
+      const Profile = t.mock('../../lib/profile.js', {
         ...mocks,
         'npm-profile': npmProfile(t),
         '../../lib/utils/read-user-info.js': readUserInfo(t),
@@ -1311,7 +1309,7 @@ t.test('disable-2fa', t => {
         if (err)
           throw err
 
-        t.deepEqual(
+        t.same(
           JSON.parse(result),
           { tfa: false },
           'should output json already disabled msg'
@@ -1323,7 +1321,7 @@ t.test('disable-2fa', t => {
     t.test('--parseable', t => {
       config.parseable = true
 
-      const Profile = requireInject('../../lib/profile.js', {
+      const Profile = t.mock('../../lib/profile.js', {
         ...mocks,
         'npm-profile': npmProfile(t),
         '../../lib/utils/read-user-info.js': readUserInfo(t),
@@ -1356,7 +1354,7 @@ t.test('disable-2fa', t => {
         return userProfile
       },
       async set (newProfile, conf) {
-        t.deepEqual(
+        t.same(
           newProfile,
           {
             tfa: {
@@ -1386,7 +1384,7 @@ t.test('disable-2fa', t => {
       },
     }
 
-    const Profile = requireInject('../../lib/profile.js', {
+    const Profile = t.mock('../../lib/profile.js', {
       ...mocks,
       'npm-profile': npmProfile,
       '../../lib/utils/read-user-info.js': readUserInfo,
diff --git a/test/lib/prune.js b/test/lib/prune.js
index 8cd148806e352..87bb1370f3a19 100644
--- a/test/lib/prune.js
+++ b/test/lib/prune.js
@@ -1,8 +1,7 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 
-test('should prune using Arborist', (t) => {
-  const Prune = requireInject('../../lib/prune.js', {
+t.test('should prune using Arborist', (t) => {
+  const Prune = t.mock('../../lib/prune.js', {
     '@npmcli/arborist': function (args) {
       t.ok(args, 'gets options object')
       t.ok(args.path, 'gets path option')
diff --git a/test/lib/publish.js b/test/lib/publish.js
index f61377b54f997..57574b22a56ea 100644
--- a/test/lib/publish.js
+++ b/test/lib/publish.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 const fs = require('fs')
 
@@ -19,10 +18,7 @@ const defaults = Object.entries(definitions).reduce((defaults, [key, def]) => {
 
 const config = defaults
 
-t.afterEach(cb => {
-  log.level = 'silent'
-  cb()
-})
+t.afterEach(() => log.level = 'silent')
 
 t.test('should publish with libnpmpublish, passing through flatOptions and respecting publishConfig.registry', (t) => {
   t.plan(7)
@@ -37,7 +33,7 @@ t.test('should publish with libnpmpublish, passing through flatOptions and respe
     }, null, 2),
   })
 
-  const Publish = requireInject('../../lib/publish.js', {
+  const Publish = t.mock('../../lib/publish.js', {
     // verify that we do NOT remove publishConfig if it was there originally
     // and then removed during the script/pack process
     libnpmpack: async () => {
@@ -50,7 +46,7 @@ t.test('should publish with libnpmpublish, passing through flatOptions and respe
     libnpmpublish: {
       publish: (manifest, tarData, opts) => {
         t.match(manifest, { name: 'my-cool-pkg', version: '1.0.0' }, 'gets manifest')
-        t.isa(tarData, Buffer, 'tarData is a buffer')
+        t.type(tarData, Buffer, 'tarData is a buffer')
         t.ok(opts, 'gets opts object')
         t.same(opts.customValue, true, 'flatOptions values are passed through')
         t.same(opts.registry, registry, 'publishConfig.registry is passed through')
@@ -88,7 +84,7 @@ t.test('re-loads publishConfig.registry if added during script process', (t) =>
     }, null, 2),
   })
 
-  const Publish = requireInject('../../lib/publish.js', {
+  const Publish = t.mock('../../lib/publish.js', {
     libnpmpack: async () => {
       fs.writeFileSync(`${testDir}/package.json`, JSON.stringify({
         name: 'my-cool-pkg',
@@ -100,7 +96,7 @@ t.test('re-loads publishConfig.registry if added during script process', (t) =>
     libnpmpublish: {
       publish: (manifest, tarData, opts) => {
         t.match(manifest, { name: 'my-cool-pkg', version: '1.0.0' }, 'gets manifest')
-        t.isa(tarData, Buffer, 'tarData is a buffer')
+        t.type(tarData, Buffer, 'tarData is a buffer')
         t.ok(opts, 'gets opts object')
         t.same(opts.registry, registry, 'publishConfig.registry is passed through')
       },
@@ -132,7 +128,7 @@ t.test('if loglevel=info and json, should not output package contents', (t) => {
   })
 
   log.level = 'info'
-  const Publish = requireInject('../../lib/publish.js', {
+  const Publish = t.mock('../../lib/publish.js', {
     '../../lib/utils/tar.js': {
       getContents: () => ({
         id: 'someid',
@@ -178,7 +174,7 @@ t.test('if loglevel=silent and dry-run, should not output package contents or pu
   })
 
   log.level = 'silent'
-  const Publish = requireInject('../../lib/publish.js', {
+  const Publish = t.mock('../../lib/publish.js', {
     '../../lib/utils/tar.js': {
       getContents: () => ({
         id: 'someid',
@@ -224,7 +220,7 @@ t.test('if loglevel=info and dry-run, should not publish, should log package con
   })
 
   log.level = 'info'
-  const Publish = requireInject('../../lib/publish.js', {
+  const Publish = t.mock('../../lib/publish.js', {
     '../../lib/utils/tar.js': {
       getContents: () => ({
         id: 'someid',
@@ -260,7 +256,7 @@ t.test('if loglevel=info and dry-run, should not publish, should log package con
 
 t.test('shows usage with wrong set of arguments', (t) => {
   t.plan(1)
-  const Publish = requireInject('../../lib/publish.js')
+  const Publish = t.mock('../../lib/publish.js')
   const publish = new Publish({})
 
   publish.exec(['a', 'b', 'c'], (er) => {
@@ -272,7 +268,7 @@ t.test('shows usage with wrong set of arguments', (t) => {
 t.test('throws when invalid tag', (t) => {
   t.plan(1)
 
-  const Publish = requireInject('../../lib/publish.js')
+  const Publish = t.mock('../../lib/publish.js')
   const npm = mockNpm({
     config: { ...config, tag: '0.0.13' },
   })
@@ -306,7 +302,7 @@ t.test('can publish a tarball', t => {
   }, ['package'])
 
   const tarFile = fs.readFileSync(`${testDir}/tarball/package.tgz`)
-  const Publish = requireInject('../../lib/publish.js', {
+  const Publish = t.mock('../../lib/publish.js', {
     libnpmpublish: {
       publish: (manifest, tarData, opts) => {
         t.match(manifest, {
@@ -334,7 +330,7 @@ t.test('can publish a tarball', t => {
 
 t.test('should check auth for default registry', t => {
   t.plan(2)
-  const Publish = requireInject('../../lib/publish.js')
+  const Publish = t.mock('../../lib/publish.js')
   const npm = mockNpm({ config })
   npm.config.getCredentialsByURI = (uri) => {
     t.same(uri, defaults.registry, 'gets credentials for expected registry')
@@ -354,7 +350,7 @@ t.test('should check auth for default registry', t => {
 t.test('should check auth for configured registry', t => {
   t.plan(2)
   const registry = 'https://some.registry'
-  const Publish = requireInject('../../lib/publish.js')
+  const Publish = t.mock('../../lib/publish.js')
   const npm = mockNpm({
     config,
     flatOptions: { registry },
@@ -384,7 +380,7 @@ t.test('should check auth for scope specific registry', t => {
     }, null, 2),
   })
 
-  const Publish = requireInject('../../lib/publish.js')
+  const Publish = t.mock('../../lib/publish.js')
   const npm = mockNpm({
     config,
     flatOptions: { '@npm:registry': registry },
@@ -414,7 +410,7 @@ t.test('should use auth for scope specific registry', t => {
     }, null, 2),
   })
 
-  const Publish = requireInject('../../lib/publish.js', {
+  const Publish = t.mock('../../lib/publish.js', {
     libnpmpublish: {
       publish: (manifest, tarData, opts) => {
         t.ok(opts, 'gets opts object')
@@ -453,7 +449,7 @@ t.test('read registry only from publishConfig', t => {
     }, null, 2),
   })
 
-  const Publish = requireInject('../../lib/publish.js', {
+  const Publish = t.mock('../../lib/publish.js', {
     libnpmpublish: {
       publish: (manifest, tarData, opts) => {
         t.match(manifest, { name: 'my-cool-pkg', version: '1.0.0' }, 'gets manifest')
@@ -499,7 +495,7 @@ t.test('able to publish after if encountered multiple configs', t => {
   }))
   configList.unshift(Object.assign(Object.create(configList[0]), { tag }))
 
-  const Publish = requireInject('../../lib/publish.js', {
+  const Publish = t.mock('../../lib/publish.js', {
     libnpmpublish: {
       publish: (manifest, tarData, opts) => {
         t.same(opts.defaultTag, tag, 'gets option for expected tag')
diff --git a/test/lib/rebuild.js b/test/lib/rebuild.js
index 6e144b7e11cc7..e686b6a32ce53 100644
--- a/test/lib/rebuild.js
+++ b/test/lib/rebuild.js
@@ -19,12 +19,11 @@ const npm = mockNpm({
 const Rebuild = require('../../lib/rebuild.js')
 const rebuild = new Rebuild(npm)
 
-t.afterEach(cb => {
+t.afterEach(() => {
   npm.prefix = ''
   config.global = false
   npm.globalDir = ''
   result = ''
-  cb()
 })
 
 t.test('no args', t => {
diff --git a/test/lib/repo.js b/test/lib/repo.js
index c05c02d80a885..0701750b58c63 100644
--- a/test/lib/repo.js
+++ b/test/lib/repo.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm.js')
 const { join, sep } = require('path')
 
@@ -186,16 +185,14 @@ const openUrl = async (npm, url, errMsg) => {
   opened[url]++
 }
 
-const Repo = requireInject('../../lib/repo.js', {
+const Repo = t.mock('../../lib/repo.js', {
   '../../lib/utils/open-url.js': openUrl,
 })
 const flatOptions = {}
 const npm = mockNpm({ flatOptions })
 const repo = new Repo(npm)
 
-t.afterEach(async () => {
-  opened = {}
-})
+t.afterEach(() => opened = {})
 
 t.test('open repo urls', t => {
   // XXX It is very odd that `where` is how pacote knows to look anywhere other
diff --git a/test/lib/root.js b/test/lib/root.js
index 4a1aefa02dcea..5460f3d4985c2 100644
--- a/test/lib/root.js
+++ b/test/lib/root.js
@@ -13,7 +13,7 @@ t.test('root', (t) => {
   })
 
   root.exec([], (err) => {
-    t.ifError(err, 'npm root')
+    t.error(err, 'npm root')
     t.ok('should have printed directory')
   })
 })
diff --git a/test/lib/run-script.js b/test/lib/run-script.js
index f7eb46fedf5eb..897c80817e254 100644
--- a/test/lib/run-script.js
+++ b/test/lib/run-script.js
@@ -1,6 +1,5 @@
 const { resolve } = require('path')
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 
 const normalizePath = p => p
@@ -43,7 +42,7 @@ const npmlog = {
   error: () => null,
 }
 
-t.afterEach(cb => {
+t.afterEach(() => {
   npm.color = false
   npmlog.level = 'warn'
   npmlog.error = () => null
@@ -52,11 +51,10 @@ t.afterEach(cb => {
   config['if-present'] = false
   config.json = false
   config.parseable = false
-  cb()
 })
 
 const getRS = windows => {
-  const RunScript = requireInject('../../lib/run-script.js', {
+  const RunScript = t.mock('../../lib/run-script.js', {
     '@npmcli/run-script': Object.assign(async opts => {
       RUN_SCRIPTS.push(opts)
     }, {
@@ -386,7 +384,7 @@ t.test('skip pre/post hooks when using ignoreScripts', t => {
     if (er)
       throw er
 
-    t.deepEqual(RUN_SCRIPTS, [
+    t.same(RUN_SCRIPTS, [
       {
         path: npm.localPrefix,
         args: [],
@@ -898,27 +896,27 @@ t.test('workspaces', t => {
         'Lifecycle script `missing-script` failed with error:',
         'Error: Missing script: "missing-script"\n\nTo see a list of scripts, run:\n  npm run',
         '  in workspace: a@1.0.0',
-        '  at location: {CWD}/test/lib/run-script-workspaces/packages/a',
+        '  at location: {CWD}/test/lib/tap-testdir-run-script-workspaces/packages/a',
         'Lifecycle script `missing-script` failed with error:',
         'Error: Missing script: "missing-script"\n\nTo see a list of scripts, run:\n  npm run',
         '  in workspace: b@2.0.0',
-        '  at location: {CWD}/test/lib/run-script-workspaces/packages/b',
+        '  at location: {CWD}/test/lib/tap-testdir-run-script-workspaces/packages/b',
         'Lifecycle script `missing-script` failed with error:',
         'Error: Missing script: "missing-script"\n\nTo see a list of scripts, run:\n  npm run',
         '  in workspace: c@1.0.0',
-        '  at location: {CWD}/test/lib/run-script-workspaces/packages/c',
+        '  at location: {CWD}/test/lib/tap-testdir-run-script-workspaces/packages/c',
         'Lifecycle script `missing-script` failed with error:',
         'Error: Missing script: "missing-script"\n\nTo see a list of scripts, run:\n  npm run',
         '  in workspace: d@1.0.0',
-        '  at location: {CWD}/test/lib/run-script-workspaces/packages/d',
+        '  at location: {CWD}/test/lib/tap-testdir-run-script-workspaces/packages/d',
         'Lifecycle script `missing-script` failed with error:',
         'Error: Missing script: "missing-script"\n\nTo see a list of scripts, run:\n  npm run',
         '  in workspace: e',
-        '  at location: {CWD}/test/lib/run-script-workspaces/packages/e',
+        '  at location: {CWD}/test/lib/tap-testdir-run-script-workspaces/packages/e',
         'Lifecycle script `missing-script` failed with error:',
         'Error: Missing script: "missing-script"\n\nTo see a list of scripts, run:\n  npm run',
         '  in workspace: noscripts@1.0.0',
-        '  at location: {CWD}/test/lib/run-script-workspaces/packages/noscripts',
+        '  at location: {CWD}/test/lib/tap-testdir-run-script-workspaces/packages/noscripts',
       ], 'should log error msgs for each workspace script')
 
       t.end()
@@ -939,11 +937,11 @@ t.test('workspaces', t => {
         'Lifecycle script `test` failed with error:',
         'Error: Missing script: "test"\n\nTo see a list of scripts, run:\n  npm run',
         '  in workspace: a@1.0.0',
-        '  at location: {CWD}/test/lib/run-script-workspaces/packages/a',
+        '  at location: {CWD}/test/lib/tap-testdir-run-script-workspaces/packages/a',
         'Lifecycle script `test` failed with error:',
         'Error: Missing script: "test"\n\nTo see a list of scripts, run:\n  npm run',
         '  in workspace: b@2.0.0',
-        '  at location: {CWD}/test/lib/run-script-workspaces/packages/b',
+        '  at location: {CWD}/test/lib/tap-testdir-run-script-workspaces/packages/b',
       ], 'should log error msgs for each workspace script')
       t.end()
     })
@@ -977,7 +975,7 @@ t.test('workspaces', t => {
   })
 
   t.test('single failed workspace run', t => {
-    const RunScript = requireInject('../../lib/run-script.js', {
+    const RunScript = t.mock('../../lib/run-script.js', {
       '@npmcli/run-script': () => {
         throw new Error('err')
       },
@@ -994,7 +992,7 @@ t.test('workspaces', t => {
   })
 
   t.test('failed workspace run with succeeded runs', t => {
-    const RunScript = requireInject('../../lib/run-script.js', {
+    const RunScript = t.mock('../../lib/run-script.js', {
       '@npmcli/run-script': async opts => {
         if (opts.pkg.name === 'a')
           throw new Error('ERR')
diff --git a/test/lib/search.js b/test/lib/search.js
index b7b40844219fb..ac894a9e3369d 100644
--- a/test/lib/search.js
+++ b/test/lib/search.js
@@ -1,6 +1,5 @@
 const Minipass = require('minipass')
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 const libnpmsearchResultFixture =
   require('../fixtures/libnpmsearch-stream-result.js')
@@ -37,15 +36,14 @@ const mocks = {
   '../../lib/utils/usage.js': () => 'usage instructions',
 }
 
-t.afterEach(cb => {
+t.afterEach(() => {
   result = ''
   config.json = false
   config.parseable = false
   npm.flatOptions = { ...flatOptions }
-  cb()
 })
 
-const Search = requireInject('../../lib/search.js', mocks)
+const Search = t.mock('../../lib/search.js', mocks)
 const search = new Search(npm)
 
 t.test('no args', t => {
@@ -68,7 +66,7 @@ t.test('search ', t => {
     },
   }
 
-  const Search = requireInject('../../lib/search.js', {
+  const Search = t.mock('../../lib/search.js', {
     ...mocks,
     libnpmsearch,
   })
@@ -101,7 +99,7 @@ t.test('search  --json', (t) => {
     },
   }
 
-  const Search = requireInject('../../lib/search.js', {
+  const Search = t.mock('../../lib/search.js', {
     ...mocks,
     libnpmsearch,
   })
@@ -146,7 +144,7 @@ t.test('search  --searchexclude --searchopts', t => {
     },
   }
 
-  const Search = requireInject('../../lib/search.js', {
+  const Search = t.mock('../../lib/search.js', {
     ...mocks,
     libnpmsearch,
   })
@@ -200,7 +198,7 @@ t.test('empty search results', t => {
     },
   }
 
-  const Search = requireInject('../../lib/search.js', {
+  const Search = t.mock('../../lib/search.js', {
     ...mocks,
     libnpmsearch,
   })
@@ -227,7 +225,7 @@ t.test('search api response error', t => {
     },
   }
 
-  const Search = requireInject('../../lib/search.js', {
+  const Search = t.mock('../../lib/search.js', {
     ...mocks,
     libnpmsearch,
   })
diff --git a/test/lib/set-script.js b/test/lib/set-script.js
index 0071fa20f247c..96b455785c509 100644
--- a/test/lib/set-script.js
+++ b/test/lib/set-script.js
@@ -1,5 +1,4 @@
-const test = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 const fs = require('fs')
 const parseJSON = require('json-parse-even-better-errors')
 const mockNpm = require('../fixtures/mock-npm.js')
@@ -10,7 +9,7 @@ const npm = mockNpm(flatOptions)
 
 const ERROR_OUTPUT = []
 const WARN_OUTPUT = []
-const SetScript = requireInject('../../lib/set-script.js', {
+const SetScript = t.mock('../../lib/set-script.js', {
   npmlog: {
     error: (...args) => {
       ERROR_OUTPUT.push(args)
@@ -22,7 +21,7 @@ const SetScript = requireInject('../../lib/set-script.js', {
 })
 const setScript = new SetScript(npm)
 
-test.test('completion', t => {
+t.test('completion', t => {
   t.test('already have a script name', async t => {
     npm.localPrefix = t.testdir({})
     const res = await setScript.completion({conf: {argv: {remain: ['npm', 'run', 'x']}}})
@@ -60,14 +59,14 @@ test.test('completion', t => {
   t.end()
 })
 
-test.test('fails on invalid arguments', (t) => {
+t.test('fails on invalid arguments', (t) => {
   t.plan(3)
   setScript.exec(['arg1'], (fail) => t.match(fail, /Expected 2 arguments: got 1/))
   setScript.exec(['arg1', 'arg2', 'arg3'], (fail) => t.match(fail, /Expected 2 arguments: got 3/))
   setScript.exec(['arg1', 'arg2', 'arg3', 'arg4'], (fail) => t.match(fail, /Expected 2 arguments: got 4/))
 })
 
-test.test('fails if run in postinstall script', (t) => {
+t.test('fails if run in postinstall script', (t) => {
   const lifecycleEvent = process.env.npm_lifecycle_event
   t.teardown(() => {
     process.env.npm_lifecycle_event = lifecycleEvent
@@ -78,12 +77,12 @@ test.test('fails if run in postinstall script', (t) => {
   setScript.exec(['arg1', 'arg2'], (fail) => t.equal(fail.toString(), 'Error: Scripts can’t set from the postinstall script'))
 })
 
-test.test('fails when package.json not found', (t) => {
+t.test('fails when package.json not found', (t) => {
   t.plan(1)
   setScript.exec(['arg1', 'arg2'], (fail) => t.match(fail, /package.json not found/))
 })
 
-test.test('fails on invalid JSON', (t) => {
+t.test('fails on invalid JSON', (t) => {
   npm.localPrefix = t.testdir({
     'package.json': 'iamnotjson',
   })
@@ -92,7 +91,7 @@ test.test('fails on invalid JSON', (t) => {
   setScript.exec(['arg1', 'arg2'], (fail) => t.match(fail, /Invalid package.json: JSONParseError/))
 })
 
-test.test('creates scripts object', (t) => {
+t.test('creates scripts object', (t) => {
   npm.localPrefix = t.testdir({
     'package.json': '{}',
   })
@@ -101,11 +100,11 @@ test.test('creates scripts object', (t) => {
   setScript.exec(['arg1', 'arg2'], (error) => {
     t.equal(error, undefined)
     const contents = fs.readFileSync(resolve(npm.localPrefix, 'package.json'))
-    t.assert(parseJSON(contents), {scripts: {arg1: 'arg2'}})
+    t.ok(parseJSON(contents), {scripts: {arg1: 'arg2'}})
   })
 })
 
-test.test('warns when overwriting', (t) => {
+t.test('warns when overwriting', (t) => {
   WARN_OUTPUT.length = 0
   npm.localPrefix = t.testdir({
     'package.json': JSON.stringify({
@@ -122,7 +121,7 @@ test.test('warns when overwriting', (t) => {
   })
 })
 
-test.test('provided indentation and eol is used', (t) => {
+t.test('provided indentation and eol is used', (t) => {
   npm.localPrefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'foo',
@@ -141,7 +140,7 @@ test.test('provided indentation and eol is used', (t) => {
   })
 })
 
-test.test('workspaces', (t) => {
+t.test('workspaces', (t) => {
   ERROR_OUTPUT.length = 0
   WARN_OUTPUT.length = 0
   npm.localPrefix = t.testdir({
diff --git a/test/lib/set.js b/test/lib/set.js
index 3b38fdc276ce2..f51065a4b293d 100644
--- a/test/lib/set.js
+++ b/test/lib/set.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 
 let configArgs = null
 const npm = {
@@ -11,7 +10,7 @@ const npm = {
   },
 }
 
-const Set = requireInject('../../lib/set.js')
+const Set = t.mock('../../lib/set.js')
 const set = new Set(npm)
 
 t.test('npm set - no args', t => {
diff --git a/test/lib/shrinkwrap.js b/test/lib/shrinkwrap.js
index faf452ea702f2..8bd18f7fbd7c6 100644
--- a/test/lib/shrinkwrap.js
+++ b/test/lib/shrinkwrap.js
@@ -1,6 +1,5 @@
 const t = require('tap')
 const fs = require('fs')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 
 const config = {
@@ -40,11 +39,10 @@ const mocks = {
   '../../lib/utils/config/definitions.js': {},
 }
 
-t.afterEach(cb => {
+t.afterEach(() => {
   npm.prefix = ''
   config.global = false
   npm.globalDir = ''
-  cb()
 })
 
 t.test('no args', t => {
@@ -54,7 +52,7 @@ t.test('no args', t => {
 
   class Arborist {
     constructor (args) {
-      t.deepEqual(
+      t.same(
         args,
         { ...flatOptions, path: npm.prefix },
         'should call arborist constructor with expected args'
@@ -85,7 +83,7 @@ t.test('no args', t => {
     },
   }
 
-  const Shrinkwrap = requireInject('../../lib/shrinkwrap.js', {
+  const Shrinkwrap = t.mock('../../lib/shrinkwrap.js', {
     ...mocks,
     npmlog,
     '@npmcli/arborist': Arborist,
@@ -105,7 +103,7 @@ t.test('no virtual tree', t => {
 
   class Arborist {
     constructor (args) {
-      t.deepEqual(
+      t.same(
         args,
         { ...flatOptions, path: npm.prefix },
         'should call arborist constructor with expected args'
@@ -140,7 +138,7 @@ t.test('no virtual tree', t => {
     },
   }
 
-  const Shrinkwrap = requireInject('../../lib/shrinkwrap.js', {
+  const Shrinkwrap = t.mock('../../lib/shrinkwrap.js', {
     ...mocks,
     npmlog,
     '@npmcli/arborist': Arborist,
@@ -160,7 +158,7 @@ t.test('existing package-json file', t => {
 
   class Arborist {
     constructor (args) {
-      t.deepEqual(
+      t.same(
         args,
         { ...flatOptions, path: npm.prefix },
         'should call arborist constructor with expected args'
@@ -201,7 +199,7 @@ t.test('existing package-json file', t => {
     },
   }
 
-  const Shrinkwrap = requireInject('../../lib/shrinkwrap.js', {
+  const Shrinkwrap = t.mock('../../lib/shrinkwrap.js', {
     ...mocks,
     fs,
     npmlog,
@@ -222,7 +220,7 @@ t.test('update shrinkwrap file version', t => {
 
   class Arborist {
     constructor (args) {
-      t.deepEqual(
+      t.same(
         args,
         { ...flatOptions, path: npm.prefix },
         'should call arborist constructor with expected args'
@@ -256,7 +254,7 @@ t.test('update shrinkwrap file version', t => {
     },
   }
 
-  const Shrinkwrap = requireInject('../../lib/shrinkwrap.js', {
+  const Shrinkwrap = t.mock('../../lib/shrinkwrap.js', {
     ...mocks,
     npmlog,
     '@npmcli/arborist': Arborist,
@@ -276,7 +274,7 @@ t.test('update to date shrinkwrap file', t => {
 
   class Arborist {
     constructor (args) {
-      t.deepEqual(
+      t.same(
         args,
         { ...flatOptions, path: npm.prefix },
         'should call arborist constructor with expected args'
@@ -310,7 +308,7 @@ t.test('update to date shrinkwrap file', t => {
     },
   }
 
-  const Shrinkwrap = requireInject('../../lib/shrinkwrap.js', {
+  const Shrinkwrap = t.mock('../../lib/shrinkwrap.js', {
     ...mocks,
     npmlog,
     '@npmcli/arborist': Arborist,
@@ -324,7 +322,7 @@ t.test('update to date shrinkwrap file', t => {
 })
 
 t.test('shrinkwrap --global', t => {
-  const Shrinkwrap = requireInject('../../lib/shrinkwrap.js', mocks)
+  const Shrinkwrap = t.mock('../../lib/shrinkwrap.js', mocks)
 
   config.global = true
   const shrinkwrap = new Shrinkwrap(npm)
@@ -342,7 +340,7 @@ t.test('shrinkwrap --global', t => {
 
 t.test('works without fs.promises', async t => {
   t.doesNotThrow(() => {
-    const Shrinkwrap = requireInject('../../lib/shrinkwrap.js', {
+    const Shrinkwrap = t.mock('../../lib/shrinkwrap.js', {
       ...mocks,
       fs: { ...fs, promises: null },
     })
diff --git a/test/lib/star.js b/test/lib/star.js
index fa75d210577ac..0c584e4a3f0cf 100644
--- a/test/lib/star.js
+++ b/test/lib/star.js
@@ -1,4 +1,3 @@
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 const t = require('tap')
 
@@ -24,15 +23,14 @@ const mocks = {
   '../../lib/utils/usage.js': () => 'usage instructions',
 }
 
-const Star = requireInject('../../lib/star.js', mocks)
+const Star = t.mock('../../lib/star.js', mocks)
 const star = new Star(npm)
 
-t.afterEach(cb => {
+t.afterEach(() => {
   config.unicode = false
   config['star.unstar'] = false
   npmlog.info = noop
   result = ''
-  cb()
 })
 
 t.test('no args', t => {
@@ -136,7 +134,7 @@ t.test('unicode', async t => {
 })
 
 t.test('logged out user', t => {
-  const Star = requireInject('../../lib/star.js', {
+  const Star = t.mock('../../lib/star.js', {
     ...mocks,
     '../../lib/utils/get-identity.js': async () => undefined,
   })
diff --git a/test/lib/stars.js b/test/lib/stars.js
index b242a883ad90f..bf345aeb4cf42 100644
--- a/test/lib/stars.js
+++ b/test/lib/stars.js
@@ -1,4 +1,3 @@
-const requireInject = require('require-inject')
 const t = require('tap')
 
 let result = ''
@@ -20,14 +19,13 @@ const mocks = {
   '../../lib/utils/usage.js': () => 'usage instructions',
 }
 
-const Stars = requireInject('../../lib/stars.js', mocks)
+const Stars = t.mock('../../lib/stars.js', mocks)
 const stars = new Stars(npm)
 
-t.afterEach(cb => {
+t.afterEach(() => {
   npm.config = { get () {} }
   npmlog.warn = noop
   result = ''
-  cb()
 })
 
 t.test('no args', t => {
diff --git a/test/lib/team.js b/test/lib/team.js
index 458f8ee6700ce..68ac28fff36ff 100644
--- a/test/lib/team.js
+++ b/test/lib/team.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 
 let result = ''
 const libnpmteam = {
@@ -23,13 +22,12 @@ const mocks = {
   '../../lib/utils/usage.js': () => 'usage instructions',
 }
 
-t.afterEach(cb => {
+t.afterEach(() => {
   result = ''
   npm.flatOptions = {}
-  cb()
 })
 
-const Team = requireInject('../../lib/team.js', mocks)
+const Team = t.mock('../../lib/team.js', mocks)
 const team = new Team(npm)
 
 t.test('no args', t => {
@@ -76,7 +74,7 @@ t.test('team add  ', t => {
       if (err)
         throw err
 
-      t.deepEqual(
+      t.same(
         JSON.parse(result),
         {
           added: true,
@@ -96,7 +94,7 @@ t.test('team add  ', t => {
       if (err)
         throw err
 
-      t.deepEqual(result, '', 'should not output success if silent')
+      t.same(result, '', 'should not output success if silent')
       t.end()
     })
   })
@@ -137,7 +135,7 @@ t.test('team create ', t => {
       if (err)
         throw err
 
-      t.deepEqual(
+      t.same(
         JSON.parse(result),
         {
           created: true,
@@ -156,7 +154,7 @@ t.test('team create ', t => {
       if (err)
         throw err
 
-      t.deepEqual(result, '', 'should not output create success if silent')
+      t.same(result, '', 'should not output create success if silent')
       t.end()
     })
   })
@@ -194,7 +192,7 @@ t.test('team destroy ', t => {
       if (err)
         throw err
 
-      t.deepEqual(
+      t.same(
         JSON.parse(result),
         {
           deleted: true,
@@ -213,7 +211,7 @@ t.test('team destroy ', t => {
       if (err)
         throw err
 
-      t.deepEqual(result, '', 'should not output destroy if silent')
+      t.same(result, '', 'should not output destroy if silent')
       t.end()
     })
   })
@@ -232,7 +230,7 @@ t.test('team ls ', t => {
     },
   }
 
-  const Team = requireInject('../../lib/team.js', {
+  const Team = t.mock('../../lib/team.js', {
     ...mocks,
     libnpmteam,
   })
@@ -267,7 +265,7 @@ t.test('team ls ', t => {
       if (err)
         throw err
 
-      t.deepEqual(
+      t.same(
         JSON.parse(result),
         [
           'npmcli:designers',
@@ -287,7 +285,7 @@ t.test('team ls ', t => {
       if (err)
         throw err
 
-      t.deepEqual(result, '', 'should not list teams if silent')
+      t.same(result, '', 'should not list teams if silent')
       t.end()
     })
   })
@@ -299,7 +297,7 @@ t.test('team ls ', t => {
       },
     }
 
-    const Team = requireInject('../../lib/team.js', {
+    const Team = t.mock('../../lib/team.js', {
       ...mocks,
       libnpmteam,
     })
@@ -321,7 +319,7 @@ t.test('team ls ', t => {
       },
     }
 
-    const Team = requireInject('../../lib/team.js', {
+    const Team = t.mock('../../lib/team.js', {
       ...mocks,
       libnpmteam,
     })
@@ -345,7 +343,7 @@ t.test('team ls ', t => {
       return ['nlf', 'ruyadorno', 'darcyclarke', 'isaacs']
     },
   }
-  const Team = requireInject('../../lib/team.js', {
+  const Team = t.mock('../../lib/team.js', {
     ...mocks,
     libnpmteam,
   })
@@ -380,7 +378,7 @@ t.test('team ls ', t => {
       if (err)
         throw err
 
-      t.deepEqual(
+      t.same(
         JSON.parse(result),
         [
           'darcyclarke',
@@ -401,7 +399,7 @@ t.test('team ls ', t => {
       if (err)
         throw err
 
-      t.deepEqual(result, '', 'should not output users if silent')
+      t.same(result, '', 'should not output users if silent')
       t.end()
     })
   })
@@ -413,7 +411,7 @@ t.test('team ls ', t => {
       },
     }
 
-    const Team = requireInject('../../lib/team.js', {
+    const Team = t.mock('../../lib/team.js', {
       ...mocks,
       libnpmteam,
     })
@@ -435,7 +433,7 @@ t.test('team ls ', t => {
       },
     }
 
-    const Team = requireInject('../../lib/team.js', {
+    const Team = t.mock('../../lib/team.js', {
       ...mocks,
       libnpmteam,
     })
@@ -483,7 +481,7 @@ t.test('team rm  ', t => {
       if (err)
         throw err
 
-      t.deepEqual(
+      t.same(
         JSON.parse(result),
         {
           removed: true,
@@ -503,7 +501,7 @@ t.test('team rm  ', t => {
       if (err)
         throw err
 
-      t.deepEqual(result, '', 'should not output rm result if silent')
+      t.same(result, '', 'should not output rm result if silent')
       t.end()
     })
   })
diff --git a/test/lib/test.js b/test/lib/test.js
index f6f3d7afb858d..c151b1e825343 100644
--- a/test/lib/test.js
+++ b/test/lib/test.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 let RUN_ARGS = null
 const npm = {
   commands: {
@@ -9,7 +8,7 @@ const npm = {
     },
   },
 }
-const Test = requireInject('../../lib/test.js')
+const Test = require('../../lib/test.js')
 const test = new Test(npm)
 
 t.test('run a test', t => {
diff --git a/test/lib/token.js b/test/lib/token.js
index 3ca44ab5c90c6..94218824d8f74 100644
--- a/test/lib/token.js
+++ b/test/lib/token.js
@@ -1,5 +1,4 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 
 const mocks = {
   profile: {},
@@ -11,7 +10,7 @@ const npm = {
   output: (...args) => mocks.output(...args),
 }
 
-const Token = requireInject('../../lib/token.js', {
+const Token = t.mock('../../lib/token.js', {
   '../../lib/utils/otplease.js': (opts, fn) => {
     return Promise.resolve().then(() => fn(opts))
   },
@@ -53,7 +52,7 @@ const tokenWithMocks = (mockRequests) => {
   return [token, reset]
 }
 
-test('completion', (t) => {
+t.test('completion', (t) => {
   t.plan(5)
 
   const testComp = (argv, expect) => {
@@ -71,7 +70,7 @@ test('completion', (t) => {
   )
 })
 
-test('token foobar', (t) => {
+t.test('token foobar', (t) => {
   t.plan(2)
 
   const [, reset] = tokenWithMocks({
@@ -84,14 +83,14 @@ test('token foobar', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['foobar'], (err) => {
     t.match(err.message, 'foobar is not a recognized subcommand')
   })
 })
 
-test('token list', (t) => {
+t.test('token list', (t) => {
   t.plan(15)
 
   const now = new Date().toISOString()
@@ -152,14 +151,14 @@ test('token list', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec([], (err) => {
-    t.ifError(err, 'npm token list')
+    t.error(err, 'npm token list')
   })
 })
 
-test('token list json output', (t) => {
+t.test('token list json output', (t) => {
   t.plan(8)
 
   const now = new Date().toISOString()
@@ -206,14 +205,14 @@ test('token list json output', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['list'], (err) => {
-    t.ifError(err, 'npm token list')
+    t.error(err, 'npm token list')
   })
 })
 
-test('token list parseable output', (t) => {
+t.test('token list parseable output', (t) => {
   t.plan(12)
 
   const now = new Date().toISOString()
@@ -274,14 +273,14 @@ test('token list parseable output', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['list'], (err) => {
-    t.ifError(err, 'npm token list')
+    t.error(err, 'npm token list')
   })
 })
 
-test('token revoke', (t) => {
+t.test('token revoke', (t) => {
   t.plan(10)
 
   const [token, reset] = tokenWithMocks({
@@ -327,14 +326,14 @@ test('token revoke', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['rm', 'abcd'], (err) => {
-    t.ifError(err, 'npm token rm')
+    t.error(err, 'npm token rm')
   })
 })
 
-test('token revoke multiple tokens', (t) => {
+t.test('token revoke multiple tokens', (t) => {
   t.plan(10)
 
   const [token, reset] = tokenWithMocks({
@@ -379,14 +378,14 @@ test('token revoke multiple tokens', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['revoke', 'abcd', 'efgh'], (err) => {
-    t.ifError(err, 'npm token rm')
+    t.error(err, 'npm token rm')
   })
 })
 
-test('token revoke json output', (t) => {
+t.test('token revoke json output', (t) => {
   t.plan(10)
 
   const [token, reset] = tokenWithMocks({
@@ -431,14 +430,14 @@ test('token revoke json output', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['delete', 'abcd'], (err) => {
-    t.ifError(err, 'npm token rm')
+    t.error(err, 'npm token rm')
   })
 })
 
-test('token revoke parseable output', (t) => {
+t.test('token revoke parseable output', (t) => {
   t.plan(9)
 
   const [token, reset] = tokenWithMocks({
@@ -481,14 +480,14 @@ test('token revoke parseable output', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['remove', 'abcd'], (err) => {
-    t.ifError(err, 'npm token rm')
+    t.error(err, 'npm token rm')
   })
 })
 
-test('token revoke by token', (t) => {
+t.test('token revoke by token', (t) => {
   t.plan(9)
 
   const [token, reset] = tokenWithMocks({
@@ -531,14 +530,14 @@ test('token revoke by token', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['rm', 'efgh5678'], (err) => {
-    t.ifError(err, 'npm token rm')
+    t.error(err, 'npm token rm')
   })
 })
 
-test('token revoke requires an id', (t) => {
+t.test('token revoke requires an id', (t) => {
   t.plan(2)
 
   const [token, reset] = tokenWithMocks({
@@ -551,14 +550,14 @@ test('token revoke requires an id', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['rm'], (err) => {
     t.match(err.message, '`` argument is required')
   })
 })
 
-test('token revoke ambiguous id errors', (t) => {
+t.test('token revoke ambiguous id errors', (t) => {
   t.plan(7)
 
   const [token, reset] = tokenWithMocks({
@@ -596,14 +595,14 @@ test('token revoke ambiguous id errors', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['rm', 'abcd'], (err) => {
     t.match(err.message, 'Token ID "abcd" was ambiguous')
   })
 })
 
-test('token revoke unknown id errors', (t) => {
+t.test('token revoke unknown id errors', (t) => {
   t.plan(7)
 
   const [token, reset] = tokenWithMocks({
@@ -640,14 +639,14 @@ test('token revoke unknown id errors', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['rm', 'efgh'], (err) => {
     t.match(err.message, 'Unknown token id or value "efgh".')
   })
 })
 
-test('token create', (t) => {
+t.test('token create', (t) => {
   t.plan(15)
 
   const now = new Date().toISOString()
@@ -704,14 +703,14 @@ test('token create', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['create'], (err) => {
-    t.ifError(err, 'npm token create')
+    t.error(err, 'npm token create')
   })
 })
 
-test('token create json output', (t) => {
+t.test('token create json output', (t) => {
   t.plan(10)
 
   const now = new Date().toISOString()
@@ -763,14 +762,14 @@ test('token create json output', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['create'], (err) => {
-    t.ifError(err, 'npm token create')
+    t.error(err, 'npm token create')
   })
 })
 
-test('token create parseable output', (t) => {
+t.test('token create parseable output', (t) => {
   t.plan(12)
 
   const now = new Date().toISOString()
@@ -829,14 +828,14 @@ test('token create parseable output', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['create'], (err) => {
-    t.ifError(err, 'npm token create')
+    t.error(err, 'npm token create')
   })
 })
 
-test('token create ipv6 cidr', (t) => {
+t.test('token create ipv6 cidr', (t) => {
   t.plan(4)
 
   const password = 'thisisnotreallyapassword'
@@ -863,7 +862,7 @@ test('token create ipv6 cidr', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['create'], (err) => {
     t.equal(err.message, 'CIDR whitelist can only contain IPv4 addresses, ::1/128 is IPv6', 'returns correct error')
@@ -871,7 +870,7 @@ test('token create ipv6 cidr', (t) => {
   })
 })
 
-test('token create invalid cidr', (t) => {
+t.test('token create invalid cidr', (t) => {
   t.plan(4)
 
   const password = 'thisisnotreallyapassword'
@@ -898,7 +897,7 @@ test('token create invalid cidr', (t) => {
     },
   })
 
-  t.tearDown(reset)
+  t.teardown(reset)
 
   token.exec(['create'], (err) => {
     t.equal(err.message, 'CIDR whitelist contains invalid CIDR entry: apple/cider', 'returns correct error')
diff --git a/test/lib/uninstall.js b/test/lib/uninstall.js
index 589191ea28e6b..8cf35bd428d3b 100644
--- a/test/lib/uninstall.js
+++ b/test/lib/uninstall.js
@@ -1,7 +1,6 @@
 const fs = require('fs')
 const { resolve } = require('path')
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 
 const npm = mockNpm({
@@ -16,16 +15,15 @@ const mocks = {
   '../../lib/utils/reify-finish.js': () => Promise.resolve(),
 }
 
-const Uninstall = requireInject('../../lib/uninstall.js', mocks)
+const Uninstall = t.mock('../../lib/uninstall.js', mocks)
 const uninstall = new Uninstall(npm)
 
-t.afterEach(cb => {
+t.afterEach(() => {
   npm.globalDir = ''
   npm.prefix = ''
   npm.localPrefix = ''
   npm.flatOptions.global = false
   npm.flatOptions.prefix = ''
-  cb()
 })
 
 t.test('remove single installed lib', t => {
@@ -231,7 +229,7 @@ t.test('no args global but no package.json', t => {
 t.test('unknown error reading from localPrefix package.json', t => {
   const path = t.testdir({})
 
-  const Uninstall = requireInject('../../lib/uninstall.js', {
+  const Uninstall = t.mock('../../lib/uninstall.js', {
     ...mocks,
     'read-package-json-fast': () => Promise.reject(new Error('ERR')),
   })
diff --git a/test/lib/unpublish.js b/test/lib/unpublish.js
index ba99b53303073..9af7242f29787 100644
--- a/test/lib/unpublish.js
+++ b/test/lib/unpublish.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 
 let result = ''
@@ -28,12 +27,11 @@ const mocks = {
   '../../lib/utils/get-identity.js': async () => 'foo',
 }
 
-t.afterEach(cb => {
+t.afterEach(() => {
   result = ''
   config.force = false
   config.loglevel = 'silly'
   config.silent = false
-  cb()
 })
 
 t.test('no args --force', t => {
@@ -66,7 +64,7 @@ t.test('no args --force', t => {
   const libnpmpublish = {
     unpublish (spec, opts) {
       t.equal(spec, 'pkg@1.0.0', 'should unpublish expected spec')
-      t.deepEqual(
+      t.same(
         opts,
         {
           publishConfig: undefined,
@@ -76,7 +74,7 @@ t.test('no args --force', t => {
     },
   }
 
-  const Unpublish = requireInject('../../lib/unpublish.js', {
+  const Unpublish = t.mock('../../lib/unpublish.js', {
     ...mocks,
     npmlog,
     libnpmpublish,
@@ -103,7 +101,7 @@ t.test('no args --force', t => {
 t.test('no args --force missing package.json', t => {
   config.force = true
 
-  const Unpublish = requireInject('../../lib/unpublish.js', {
+  const Unpublish = t.mock('../../lib/unpublish.js', {
     ...mocks,
     'read-package-json': (path, cb) => cb(Object.assign(
       new Error('ENOENT'),
@@ -125,7 +123,7 @@ t.test('no args --force missing package.json', t => {
 t.test('no args --force unknown error reading package.json', t => {
   config.force = true
 
-  const Unpublish = requireInject('../../lib/unpublish.js', {
+  const Unpublish = t.mock('../../lib/unpublish.js', {
     ...mocks,
     'read-package-json': (path, cb) => cb(new Error('ERR')),
   })
@@ -142,7 +140,7 @@ t.test('no args --force unknown error reading package.json', t => {
 })
 
 t.test('no args', t => {
-  const Unpublish = requireInject('../../lib/unpublish.js', {
+  const Unpublish = t.mock('../../lib/unpublish.js', {
     ...mocks,
   })
   const unpublish = new Unpublish(npm)
@@ -158,7 +156,7 @@ t.test('no args', t => {
 })
 
 t.test('too many args', t => {
-  const Unpublish = requireInject('../../lib/unpublish.js', {
+  const Unpublish = t.mock('../../lib/unpublish.js', {
     ...mocks,
   })
   const unpublish = new Unpublish(npm)
@@ -197,7 +195,7 @@ t.test('unpublish @version', t => {
   const libnpmpublish = {
     unpublish (spec, opts) {
       t.equal(spec, pa, 'should unpublish expected parsed spec')
-      t.deepEqual(
+      t.same(
         opts,
         {},
         'should unpublish with expected opts'
@@ -205,7 +203,7 @@ t.test('unpublish @version', t => {
     },
   }
 
-  const Unpublish = requireInject('../../lib/unpublish.js', {
+  const Unpublish = t.mock('../../lib/unpublish.js', {
     ...mocks,
     npmlog,
     libnpmpublish,
@@ -235,7 +233,7 @@ t.test('no version found in package.json', t => {
 
   npa.resolve = () => ''
 
-  const Unpublish = requireInject('../../lib/unpublish.js', {
+  const Unpublish = t.mock('../../lib/unpublish.js', {
     ...mocks,
     'npm-package-arg': npa,
     'read-package-json': (path, cb) => cb(null, {
@@ -260,7 +258,7 @@ t.test('no version found in package.json', t => {
 t.test('unpublish  --force no version set', t => {
   config.force = true
 
-  const Unpublish = requireInject('../../lib/unpublish.js', {
+  const Unpublish = t.mock('../../lib/unpublish.js', {
     ...mocks,
     'npm-package-arg': () => ({
       name: 'pkg',
@@ -294,7 +292,7 @@ t.test('silent', t => {
 
   npa.resolve = () => ''
 
-  const Unpublish = requireInject('../../lib/unpublish.js', {
+  const Unpublish = t.mock('../../lib/unpublish.js', {
     ...mocks,
     'npm-package-arg': npa,
   })
@@ -323,7 +321,7 @@ t.test('completion', async t => {
     }
 
   t.test('completing with multiple versions from the registry', async t => {
-    const Unpublish = requireInject('../../lib/unpublish.js', {
+    const Unpublish = t.mock('../../lib/unpublish.js', {
       ...mocks,
       libnpmaccess: {
         async lsPackages () {
@@ -361,7 +359,7 @@ t.test('completion', async t => {
   })
 
   t.test('no versions retrieved', async t => {
-    const Unpublish = requireInject('../../lib/unpublish.js', {
+    const Unpublish = t.mock('../../lib/unpublish.js', {
       ...mocks,
       libnpmaccess: {
         async lsPackages () {
@@ -394,7 +392,7 @@ t.test('completion', async t => {
   })
 
   t.test('packages starting with same letters', async t => {
-    const Unpublish = requireInject('../../lib/unpublish.js', {
+    const Unpublish = t.mock('../../lib/unpublish.js', {
       ...mocks,
       libnpmaccess: {
         async lsPackages () {
@@ -422,7 +420,7 @@ t.test('completion', async t => {
   })
 
   t.test('no packages retrieved', async t => {
-    const Unpublish = requireInject('../../lib/unpublish.js', {
+    const Unpublish = t.mock('../../lib/unpublish.js', {
       ...mocks,
       libnpmaccess: {
         async lsPackages () {
@@ -442,7 +440,7 @@ t.test('completion', async t => {
   })
 
   t.test('no pkg name to complete', async t => {
-    const Unpublish = requireInject('../../lib/unpublish.js', {
+    const Unpublish = t.mock('../../lib/unpublish.js', {
       ...mocks,
       libnpmaccess: {
         async lsPackages () {
@@ -465,7 +463,7 @@ t.test('completion', async t => {
   })
 
   t.test('no pkg names retrieved from user account', async t => {
-    const Unpublish = requireInject('../../lib/unpublish.js', {
+    const Unpublish = t.mock('../../lib/unpublish.js', {
       ...mocks,
       libnpmaccess: {
         async lsPackages () {
@@ -485,7 +483,7 @@ t.test('completion', async t => {
   })
 
   t.test('logged out user', async t => {
-    const Unpublish = requireInject('../../lib/unpublish.js', {
+    const Unpublish = t.mock('../../lib/unpublish.js', {
       ...mocks,
       '../../lib/utils/get-identity.js': () => Promise.reject(new Error('ERR')),
     })
@@ -500,7 +498,7 @@ t.test('completion', async t => {
   })
 
   t.test('too many args', async t => {
-    const Unpublish = requireInject('../../lib/unpublish.js', mocks)
+    const Unpublish = t.mock('../../lib/unpublish.js', mocks)
     const unpublish = new Unpublish(npm)
 
     await testComp(t, {
diff --git a/test/lib/unstar.js b/test/lib/unstar.js
index 3f3487176d995..8b853230a6c8b 100644
--- a/test/lib/unstar.js
+++ b/test/lib/unstar.js
@@ -1,4 +1,3 @@
-const requireInject = require('require-inject')
 const t = require('tap')
 
 t.test('unstar', t => {
@@ -10,11 +9,11 @@ t.test('unstar', t => {
     }
 
     exec (args, cb) {
-      t.deepEqual(args, ['pkg'], 'should forward packages')
+      t.same(args, ['pkg'], 'should forward packages')
       cb()
     }
   }
-  const Unstar = requireInject('../../lib/unstar.js', {
+  const Unstar = t.mock('../../lib/unstar.js', {
     '../../lib/star.js': Star,
   })
 
diff --git a/test/lib/update.js b/test/lib/update.js
index 780484afbeb03..5396397d520cf 100644
--- a/test/lib/update.js
+++ b/test/lib/update.js
@@ -1,6 +1,5 @@
 const { resolve } = require('path')
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 
 const config = {
@@ -23,11 +22,10 @@ const mocks = {
   '../../lib/utils/usage.js': () => 'usage instructions',
 }
 
-t.afterEach(cb => {
+t.afterEach(() => {
   npm.prefix = ''
   config.global = false
   npm.globalDir = ''
-  cb()
 })
 
 t.test('no args', t => {
@@ -37,7 +35,7 @@ t.test('no args', t => {
 
   class Arborist {
     constructor (args) {
-      t.deepEqual(
+      t.same(
         args,
         { ...npm.flatOptions, path: npm.prefix, log: noop },
         'should call arborist contructor with expected args'
@@ -49,10 +47,10 @@ t.test('no args', t => {
     }
   }
 
-  const Update = requireInject('../../lib/update.js', {
+  const Update = t.mock('../../lib/update.js', {
     ...mocks,
     '../../lib/utils/reify-finish.js': (npm, arb) => {
-      t.isLike(arb, Arborist, 'should reify-finish with arborist instance')
+      t.match(arb, Arborist, 'should reify-finish with arborist instance')
     },
     '@npmcli/arborist': Arborist,
   })
@@ -71,7 +69,7 @@ t.test('with args', t => {
 
   class Arborist {
     constructor (args) {
-      t.deepEqual(
+      t.same(
         args,
         { ...npm.flatOptions, path: npm.prefix, log: noop },
         'should call arborist contructor with expected args'
@@ -79,14 +77,14 @@ t.test('with args', t => {
     }
 
     reify ({ update }) {
-      t.deepEqual(update, ['ipt'], 'should update listed deps')
+      t.same(update, ['ipt'], 'should update listed deps')
     }
   }
 
-  const Update = requireInject('../../lib/update.js', {
+  const Update = t.mock('../../lib/update.js', {
     ...mocks,
     '../../lib/utils/reify-finish.js': (npm, arb) => {
-      t.isLike(arb, Arborist, 'should reify-finish with arborist instance')
+      t.match(arb, Arborist, 'should reify-finish with arborist instance')
     },
     '@npmcli/arborist': Arborist,
   })
@@ -104,7 +102,7 @@ t.test('update --depth=', t => {
   npm.prefix = '/project/a'
   config.depth = 1
 
-  const Update = requireInject('../../lib/update.js', {
+  const Update = t.mock('../../lib/update.js', {
     ...mocks,
     npmlog: {
       warn: (title, msg) => {
@@ -139,7 +137,7 @@ t.test('update --global', t => {
   class Arborist {
     constructor (args) {
       const { path, ...opts } = args
-      t.deepEqual(
+      t.same(
         opts,
         { ...npm.flatOptions, log: noop },
         'should call arborist contructor with expected options'
@@ -155,7 +153,7 @@ t.test('update --global', t => {
     reify () {}
   }
 
-  const Update = requireInject('../../lib/update.js', {
+  const Update = t.mock('../../lib/update.js', {
     ...mocks,
     '@npmcli/arborist': Arborist,
   })
diff --git a/test/lib/utils/audit-error.js b/test/lib/utils/audit-error.js
index d236f4f9e9eaf..c683053cbf787 100644
--- a/test/lib/utils/audit-error.js
+++ b/test/lib/utils/audit-error.js
@@ -13,11 +13,10 @@ const npm = {
   },
   output,
 }
-t.afterEach(cb => {
+t.afterEach(() => {
   npm.flatOptions = {}
   OUTPUT.length = 0
   LOGS.length = 0
-  cb()
 })
 
 t.test('no error, not audit command', t => {
diff --git a/test/lib/utils/cleanup-log-files.js b/test/lib/utils/cleanup-log-files.js
index 7af0633fe715d..61240b7b523de 100644
--- a/test/lib/utils/cleanup-log-files.js
+++ b/test/lib/utils/cleanup-log-files.js
@@ -1,10 +1,9 @@
 const t = require('tap')
 
-const requireInject = require('require-inject')
 const glob = require('glob')
 const rimraf = require('rimraf')
 const mocks = { glob, rimraf }
-const cleanup = requireInject('../../../lib/utils/cleanup-log-files.js', {
+const cleanup = t.mock('../../../lib/utils/cleanup-log-files.js', {
   glob: (...args) => mocks.glob(...args),
   rimraf: (...args) => mocks.rimraf(...args),
 })
diff --git a/test/lib/utils/completion/installed-deep.js b/test/lib/utils/completion/installed-deep.js
index 0e80a5a1983da..ba14798bbec18 100644
--- a/test/lib/utils/completion/installed-deep.js
+++ b/test/lib/utils/completion/installed-deep.js
@@ -1,6 +1,5 @@
 const { resolve } = require('path')
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 
 let prefix
 let globalDir = 'MISSING_GLOBAL_DIR'
@@ -12,7 +11,7 @@ const _flatOptions = {
   },
 }
 const p = '../../../../lib/utils/completion/installed-deep.js'
-const installedDeep = requireInject(p)
+const installedDeep = require(p)
 const npm = {
   flatOptions: _flatOptions,
   get prefix () {
@@ -144,7 +143,7 @@ const globalFixture = {
   },
 }
 
-test('get list of package names', async t => {
+t.test('get list of package names', async t => {
   const fix = t.testdir({
     local: fixture,
     global: globalFixture,
@@ -154,7 +153,7 @@ test('get list of package names', async t => {
   globalDir = resolve(fix, 'global/node_modules')
 
   const res = await installedDeep(npm, null)
-  t.deepEqual(
+  t.same(
     res,
     [
       ['bar', '-g'],
@@ -169,7 +168,7 @@ test('get list of package names', async t => {
   t.end()
 })
 
-test('get list of package names as global', async t => {
+t.test('get list of package names as global', async t => {
   const fix = t.testdir({
     local: fixture,
     global: globalFixture,
@@ -181,7 +180,7 @@ test('get list of package names as global', async t => {
   _flatOptions.global = true
 
   const res = await installedDeep(npm, null)
-  t.deepEqual(
+  t.same(
     res,
     [
       'bar',
@@ -194,7 +193,7 @@ test('get list of package names as global', async t => {
   t.end()
 })
 
-test('limit depth', async t => {
+t.test('limit depth', async t => {
   const fix = t.testdir({
     local: fixture,
     global: globalFixture,
@@ -206,7 +205,7 @@ test('limit depth', async t => {
   _flatOptions.depth = 0
 
   const res = await installedDeep(npm, null)
-  t.deepEqual(
+  t.same(
     res,
     [
       ['bar', '-g'],
@@ -222,7 +221,7 @@ test('limit depth', async t => {
   t.end()
 })
 
-test('limit depth as global', async t => {
+t.test('limit depth as global', async t => {
   const fix = t.testdir({
     local: fixture,
     global: globalFixture,
@@ -235,7 +234,7 @@ test('limit depth as global', async t => {
   _flatOptions.depth = 0
 
   const res = await installedDeep(npm, null)
-  t.deepEqual(
+  t.same(
     res,
     [
       'bar',
diff --git a/test/lib/utils/completion/installed-shallow.js b/test/lib/utils/completion/installed-shallow.js
index 1067a50acd4bb..1445cbf2ffb71 100644
--- a/test/lib/utils/completion/installed-shallow.js
+++ b/test/lib/utils/completion/installed-shallow.js
@@ -1,11 +1,10 @@
-const requireInject = require('require-inject')
 const flatOptions = { global: false }
 const npm = { flatOptions }
 const t = require('tap')
 const { resolve } = require('path')
 
 const p = '../../../../lib/utils/completion/installed-shallow.js'
-const installed = requireInject(p)
+const installed = require(p)
 
 t.test('global not set, include globals with -g', async t => {
   const dir = t.testdir({
diff --git a/test/lib/utils/config/definitions.js b/test/lib/utils/config/definitions.js
index 0b80b34d55771..dce69b7f6eda8 100644
--- a/test/lib/utils/config/definitions.js
+++ b/test/lib/utils/config/definitions.js
@@ -1,6 +1,5 @@
 const t = require('tap')
 
-const requireInject = require('require-inject')
 const { resolve } = require('path')
 
 // have to fake the node version, or else it'll only pass on this one
@@ -40,25 +39,25 @@ t.test('editor', t => {
   t.test('has EDITOR and VISUAL, use EDITOR', t => {
     process.env.EDITOR = 'vim'
     process.env.VISUAL = 'mate'
-    const defs = requireInject(defpath)
+    const defs = t.mock(defpath)
     t.equal(defs.editor.default, 'vim')
     t.end()
   })
   t.test('has VISUAL but no EDITOR, use VISUAL', t => {
     delete process.env.EDITOR
     process.env.VISUAL = 'mate'
-    const defs = requireInject(defpath)
+    const defs = t.mock(defpath)
     t.equal(defs.editor.default, 'mate')
     t.end()
   })
   t.test('has neither EDITOR nor VISUAL, system specific', t => {
     delete process.env.EDITOR
     delete process.env.VISUAL
-    const defsWin = requireInject(defpath, {
+    const defsWin = t.mock(defpath, {
       [isWin]: true,
     })
     t.equal(defsWin.editor.default, 'notepad.exe')
-    const defsNix = requireInject(defpath, {
+    const defsNix = t.mock(defpath, {
       [isWin]: false,
     })
     t.equal(defsNix.editor.default, 'vi')
@@ -70,12 +69,12 @@ t.test('editor', t => {
 t.test('shell', t => {
   t.test('windows, env.ComSpec then cmd.exe', t => {
     process.env.ComSpec = 'command.com'
-    const defsComSpec = requireInject(defpath, {
+    const defsComSpec = t.mock(defpath, {
       [isWin]: true,
     })
     t.equal(defsComSpec.shell.default, 'command.com')
     delete process.env.ComSpec
-    const defsNoComSpec = requireInject(defpath, {
+    const defsNoComSpec = t.mock(defpath, {
       [isWin]: true,
     })
     t.equal(defsNoComSpec.shell.default, 'cmd')
@@ -84,12 +83,12 @@ t.test('shell', t => {
 
   t.test('nix, SHELL then sh', t => {
     process.env.SHELL = '/usr/local/bin/bash'
-    const defsShell = requireInject(defpath, {
+    const defsShell = t.mock(defpath, {
       [isWin]: false,
     })
     t.equal(defsShell.shell.default, '/usr/local/bin/bash')
     delete process.env.SHELL
-    const defsNoShell = requireInject(defpath, {
+    const defsNoShell = t.mock(defpath, {
       [isWin]: false,
     })
     t.equal(defsNoShell.shell.default, 'sh')
@@ -108,7 +107,7 @@ t.test('local-address allowed types', t => {
         eth69: [{ address: 'no place like home' }],
       }),
     }
-    const defs = requireInject(defpath, { os })
+    const defs = t.mock(defpath, { os })
     t.same(defs['local-address'].type, [
       null,
       '127.0.0.1',
@@ -123,7 +122,7 @@ t.test('local-address allowed types', t => {
         throw new Error('no network interfaces for some reason')
       },
     }
-    const defs = requireInject(defpath, { os })
+    const defs = t.mock(defpath, { os })
     t.same(defs['local-address'].type, [null])
     t.end()
   })
@@ -138,42 +137,42 @@ t.test('unicode allowed?', t => {
   process.env.LC_CTYPE = 'UTF-8'
   process.env.LANG = 'Unicode utf-8'
 
-  const lcAll = requireInject(defpath)
+  const lcAll = t.mock(defpath)
   t.equal(lcAll.unicode.default, true)
   process.env.LC_ALL = 'no unicode for youUUUU!'
-  const noLcAll = requireInject(defpath)
+  const noLcAll = t.mock(defpath)
   t.equal(noLcAll.unicode.default, false)
 
   delete process.env.LC_ALL
-  const lcCtype = requireInject(defpath)
+  const lcCtype = t.mock(defpath)
   t.equal(lcCtype.unicode.default, true)
   process.env.LC_CTYPE = 'something other than unicode version 8'
-  const noLcCtype = requireInject(defpath)
+  const noLcCtype = t.mock(defpath)
   t.equal(noLcCtype.unicode.default, false)
 
   delete process.env.LC_CTYPE
-  const lang = requireInject(defpath)
+  const lang = t.mock(defpath)
   t.equal(lang.unicode.default, true)
   process.env.LANG = 'ISO-8859-1'
-  const noLang = requireInject(defpath)
+  const noLang = t.mock(defpath)
   t.equal(noLang.unicode.default, false)
   t.end()
 })
 
 t.test('cache', t => {
   process.env.LOCALAPPDATA = 'app/data/local'
-  const defsWinLocalAppData = requireInject(defpath, {
+  const defsWinLocalAppData = t.mock(defpath, {
     [isWin]: true,
   })
   t.equal(defsWinLocalAppData.cache.default, 'app/data/local/npm-cache')
 
   delete process.env.LOCALAPPDATA
-  const defsWinNoLocalAppData = requireInject(defpath, {
+  const defsWinNoLocalAppData = t.mock(defpath, {
     [isWin]: true,
   })
   t.equal(defsWinNoLocalAppData.cache.default, '~/npm-cache')
 
-  const defsNix = requireInject(defpath, {
+  const defsNix = t.mock(defpath, {
     [isWin]: false,
   })
   t.equal(defsNix.cache.default, '~/.npm')
@@ -236,7 +235,7 @@ t.test('flatteners that populate flat.omit array', t => {
     t.strictSame(flat, { omit: ['optional'] }, 'do not omit what is included')
 
     process.env.NODE_ENV = 'production'
-    const defProdEnv = requireInject(defpath)
+    const defProdEnv = t.mock(defpath)
     t.strictSame(defProdEnv.omit.default, ['dev'], 'omit dev in production')
     t.end()
   })
@@ -388,15 +387,15 @@ t.test('color', t => {
   t.strictSame(flat, {color: true}, '--color turns on color when stdout is tty')
 
   delete process.env.NO_COLOR
-  const defsAllowColor = requireInject(defpath)
+  const defsAllowColor = t.mock(defpath)
   t.equal(defsAllowColor.color.default, true, 'default true when no NO_COLOR env')
 
   process.env.NO_COLOR = '0'
-  const defsNoColor0 = requireInject(defpath)
+  const defsNoColor0 = t.mock(defpath)
   t.equal(defsNoColor0.color.default, true, 'default true when no NO_COLOR=0')
 
   process.env.NO_COLOR = '1'
-  const defsNoColor1 = requireInject(defpath)
+  const defsNoColor1 = t.mock(defpath)
   t.equal(defsNoColor1.color.default, false, 'default false when no NO_COLOR=1')
 
   t.end()
@@ -695,7 +694,7 @@ YYYY\r
   })
   t.test('error other than ENOENT gets thrown', t => {
     const poo = new Error('poo')
-    const defnReadFileThrows = requireInject(defpath, {
+    const defnReadFileThrows = t.mock(defpath, {
       fs: {
         ...require('fs'),
         readFileSync: () => {
@@ -711,10 +710,10 @@ YYYY\r
 })
 
 t.test('detect CI', t => {
-  const defnNoCI = requireInject(defpath, {
+  const defnNoCI = t.mock(defpath, {
     '@npmcli/ci-detect': () => false,
   })
-  const defnCIFoo = requireInject(defpath, {
+  const defnCIFoo = t.mock(defpath, {
     '@npmcli/ci-detect': () => 'foo',
   })
   t.equal(defnNoCI['ci-name'].default, null, 'null when not in CI')
diff --git a/test/lib/utils/did-you-mean.js b/test/lib/utils/did-you-mean.js
index 68893a800fda4..15712b665be6e 100644
--- a/test/lib/utils/did-you-mean.js
+++ b/test/lib/utils/did-you-mean.js
@@ -1,6 +1,5 @@
 const t = require('tap')
-const requireInject = require('require-inject')
-const npm = requireInject('../../../lib/npm.js')
+const npm = require('../../../lib/npm.js')
 
 const dym = require('../../../lib/utils/did-you-mean.js')
 t.test('did-you-mean', t => {
diff --git a/test/lib/utils/error-handler.js b/test/lib/utils/error-handler.js
index b1d3e2ca7ca1a..a00bac76e11c2 100644
--- a/test/lib/utils/error-handler.js
+++ b/test/lib/utils/error-handler.js
@@ -1,7 +1,6 @@
 /* eslint-disable no-extend-native */
 /* eslint-disable no-global-assign */
 const EventEmitter = require('events')
-const requireInject = require('require-inject')
 const t = require('tap')
 
 // NOTE: Although these unit tests may look like the rest on the surface,
@@ -105,6 +104,7 @@ process = Object.assign(
       cb()
     } },
     stderr: { write () {} },
+    hrtime: _process.hrtime,
   }
 )
 // needs to put process back in its place
@@ -124,8 +124,7 @@ const mocks = {
   '../../../lib/utils/cache-file.js': cacheFile,
 }
 
-requireInject.installGlobally('../../../lib/utils/error-handler.js', mocks)
-let errorHandler = require('../../../lib/utils/error-handler.js')
+let errorHandler = t.mock('../../../lib/utils/error-handler.js', mocks)
 
 t.test('default exit code', (t) => {
   t.plan(1)
@@ -226,7 +225,7 @@ t.test('console.log output using --json', (t) => {
 
   const _error = console.error
   console.error = (jsonOutput) => {
-    t.deepEqual(
+    t.same(
       JSON.parse(jsonOutput),
       {
         error: {
@@ -258,7 +257,7 @@ t.test('throw a non-error obj', (t) => {
   const _logError = npmlog.error
   npmlog.error = (title, err) => {
     t.equal(title, 'weird error', 'should name it a weird error')
-    t.deepEqual(err, weirdError, 'should log given weird error')
+    t.same(err, weirdError, 'should log given weird error')
   }
 
   const _exit = process.exit
@@ -282,7 +281,7 @@ t.test('throw a string error', (t) => {
   const _logError = npmlog.error
   npmlog.error = (title, err) => {
     t.equal(title, '', 'should have an empty name ref')
-    t.deepEqual(err, 'foo bar', 'should log string error')
+    t.same(err, 'foo bar', 'should log string error')
   }
 
   const _exit = process.exit
@@ -372,9 +371,7 @@ t.test('it worked', (t) => {
 t.test('uses code from errno', (t) => {
   t.plan(1)
 
-  // RESET MODULE INTERNAL VARS AND GLOBAL REFS
-  requireInject.installGlobally.andClearCache('../../../lib/utils/error-handler.js', mocks)
-  errorHandler = require('../../../lib/utils/error-handler.js')
+  errorHandler = t.mock('../../../lib/utils/error-handler.js', mocks)
 
   npmlog.level = 'silent'
   const _exit = process.exit
@@ -398,12 +395,7 @@ t.test('uses code from errno', (t) => {
 t.test('uses exitCode as code if using a number', (t) => {
   t.plan(1)
 
-  // RESET MODULE INTERNAL VARS AND GLOBAL REFS
-  requireInject.installGlobally.andClearCache(
-    '../../../lib/utils/error-handler.js',
-    mocks
-  )
-  errorHandler = require('../../../lib/utils/error-handler.js')
+  errorHandler = t.mock('../../../lib/utils/error-handler.js', mocks)
 
   npmlog.level = 'silent'
   const _exit = process.exit
@@ -427,12 +419,7 @@ t.test('uses exitCode as code if using a number', (t) => {
 t.test('call errorHandler with no error', (t) => {
   t.plan(1)
 
-  // RESET MODULE INTERNAL VARS AND GLOBAL REFS
-  requireInject.installGlobally.andClearCache(
-    '../../../lib/utils/error-handler.js',
-    mocks
-  )
-  errorHandler = require('../../../lib/utils/error-handler.js')
+  errorHandler = t.mock('../../../lib/utils/error-handler.js', mocks)
 
   const _exit = process.exit
   process.exit = (code) => {
@@ -490,12 +477,7 @@ t.test('defaults to log error msg if stack is missing', (t) => {
 t.test('set it worked', (t) => {
   t.plan(1)
 
-  // RESET MODULE INTERNAL VARS AND GLOBAL REFS
-  requireInject.installGlobally.andClearCache(
-    '../../../lib/utils/error-handler.js',
-    mocks
-  )
-  errorHandler = require('../../../lib/utils/error-handler.js')
+  errorHandler = t.mock('../../../lib/utils/error-handler.js', mocks)
 
   const _exit = process.exit
   process.exit = () => {
@@ -550,10 +532,7 @@ t.test('do no fancy handling for shellouts', t => {
     t.equal(code, EXPECT_EXIT, 'got expected exit code')
     EXPECT_EXIT = 0
   }
-  t.beforeEach((cb) => {
-    LOG_RECORD.length = 0
-    cb()
-  })
+  t.beforeEach(() => LOG_RECORD.length = 0)
 
   const loudNoises = () => LOG_RECORD
     .filter(({ level }) => ['warn', 'error'].includes(level))
diff --git a/test/lib/utils/error-message.js b/test/lib/utils/error-message.js
index 86db7c94bad49..7529aac2d4a4b 100644
--- a/test/lib/utils/error-message.js
+++ b/test/lib/utils/error-message.js
@@ -10,22 +10,6 @@ Object.defineProperty(process, 'arch', {
   configurable: true,
 })
 
-const beWindows = () => {
-  Object.defineProperty(process, 'platform', {
-    value: 'win32',
-    configurable: true,
-  })
-  delete require.cache[require.resolve('../../../lib/utils/is-windows.js')]
-}
-
-const bePosix = () => {
-  Object.defineProperty(process, 'platform', {
-    value: 'posix',
-    configurable: true,
-  })
-  delete require.cache[require.resolve('../../../lib/utils/is-windows.js')]
-}
-
 const { resolve } = require('path')
 const npm = require('../../../lib/npm.js')
 const CACHE = '/some/cache/dir'
@@ -56,16 +40,36 @@ npmlog.verbose = (...message) => {
   verboseLogs.push(message)
 }
 
-const requireInject = require('require-inject')
 const EXPLAIN_CALLED = []
-const errorMessage = requireInject('../../../lib/utils/error-message.js', {
+const mocks = {
   '../../../lib/utils/explain-eresolve.js': {
     report: (...args) => {
       EXPLAIN_CALLED.push(args)
       return 'explanation'
     },
   },
-})
+  '../../../lib/npm.js': require('../../../lib/npm.js'),
+  get '../../../lib/utils/is-windows.js' () {
+    return process.platform === 'win32'
+  },
+}
+let errorMessage = t.mock('../../../lib/utils/error-message.js', { ...mocks })
+
+const beWindows = () => {
+  Object.defineProperty(process, 'platform', {
+    value: 'win32',
+    configurable: true,
+  })
+  errorMessage = t.mock('../../../lib/utils/error-message.js', { ...mocks })
+}
+
+const bePosix = () => {
+  Object.defineProperty(process, 'platform', {
+    value: 'posix',
+    configurable: true,
+  })
+  errorMessage = t.mock('../../../lib/utils/error-message.js', { ...mocks })
+}
 
 t.test('just simple messages', t => {
   npm.command = 'audit'
diff --git a/test/lib/utils/explain-dep.js b/test/lib/utils/explain-dep.js
index 1fee6105081e9..cab4d7b59a3e6 100644
--- a/test/lib/utils/explain-dep.js
+++ b/test/lib/utils/explain-dep.js
@@ -1,7 +1,6 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const npm = {}
-const { explainNode, printNode } = requireInject('../../../lib/utils/explain-dep.js', {
+const { explainNode, printNode } = t.mock('../../../lib/utils/explain-dep.js', {
   '../../../lib/npm.js': npm,
 })
 
diff --git a/test/lib/utils/explain-eresolve.js b/test/lib/utils/explain-eresolve.js
index 8dae1b92cd514..90795bb4470b2 100644
--- a/test/lib/utils/explain-eresolve.js
+++ b/test/lib/utils/explain-eresolve.js
@@ -1,7 +1,6 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const npm = {}
-const { explain, report } = requireInject('../../../lib/utils/explain-eresolve.js', {
+const { explain, report } = t.mock('../../../lib/utils/explain-eresolve.js', {
   '../../../lib/npm.js': npm,
 })
 const { statSync, readFileSync, unlinkSync } = require('fs')
diff --git a/test/lib/utils/file-exists.js b/test/lib/utils/file-exists.js
index 473a4b050edef..c8edf4d968a0f 100644
--- a/test/lib/utils/file-exists.js
+++ b/test/lib/utils/file-exists.js
@@ -1,7 +1,7 @@
-const { test } = require('tap')
+const t = require('tap')
 const fileExists = require('../../../lib/utils/file-exists.js')
 
-test('returns true when arg is a file', async (t) => {
+t.test('returns true when arg is a file', async (t) => {
   const path = t.testdir({
     foo: 'just some file',
   })
@@ -11,7 +11,7 @@ test('returns true when arg is a file', async (t) => {
   t.end()
 })
 
-test('returns false when arg is not a file', async (t) => {
+t.test('returns false when arg is not a file', async (t) => {
   const path = t.testdir({
     foo: {},
   })
@@ -21,7 +21,7 @@ test('returns false when arg is not a file', async (t) => {
   t.end()
 })
 
-test('returns false when arg does not exist', async (t) => {
+t.test('returns false when arg does not exist', async (t) => {
   const path = t.testdir()
 
   const result = await fileExists(`${path}/foo`)
diff --git a/test/lib/utils/get-identity.js b/test/lib/utils/get-identity.js
index cc713b3378166..5e6de9ca9cfee 100644
--- a/test/lib/utils/get-identity.js
+++ b/test/lib/utils/get-identity.js
@@ -1,9 +1,8 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 
-test('throws ENOREGISTRY when no registry option is provided', async (t) => {
+t.test('throws ENOREGISTRY when no registry option is provided', async (t) => {
   t.plan(2)
-  const getIdentity = requireInject('../../../lib/utils/get-identity.js')
+  const getIdentity = t.mock('../../../lib/utils/get-identity.js')
 
   try {
     await getIdentity({})
@@ -13,10 +12,10 @@ test('throws ENOREGISTRY when no registry option is provided', async (t) => {
   }
 })
 
-test('returns username from uri when provided', async (t) => {
+t.test('returns username from uri when provided', async (t) => {
   t.plan(1)
 
-  const getIdentity = requireInject('../../../lib/utils/get-identity.js')
+  const getIdentity = t.mock('../../../lib/utils/get-identity.js')
   const npm = {
     config: {
       getCredentialsByURI: () => {
@@ -29,7 +28,7 @@ test('returns username from uri when provided', async (t) => {
   t.equal(identity, 'foo', 'returns username from uri')
 })
 
-test('calls registry whoami when token is provided', async (t) => {
+t.test('calls registry whoami when token is provided', async (t) => {
   t.plan(3)
 
   const options = {
@@ -37,7 +36,7 @@ test('calls registry whoami when token is provided', async (t) => {
     token: 'thisisnotreallyatoken',
   }
 
-  const getIdentity = requireInject('../../../lib/utils/get-identity.js', {
+  const getIdentity = t.mock('../../../lib/utils/get-identity.js', {
     'npm-registry-fetch': {
       json: (path, opts) => {
         t.equal(path, '/-/whoami', 'calls whoami')
@@ -56,7 +55,7 @@ test('calls registry whoami when token is provided', async (t) => {
   t.equal(identity, 'foo', 'fetched username from registry')
 })
 
-test('throws ENEEDAUTH when response does not include a username', async (t) => {
+t.test('throws ENEEDAUTH when response does not include a username', async (t) => {
   t.plan(3)
 
   const options = {
@@ -64,7 +63,7 @@ test('throws ENEEDAUTH when response does not include a username', async (t) =>
     token: 'thisisnotreallyatoken',
   }
 
-  const getIdentity = requireInject('../../../lib/utils/get-identity.js', {
+  const getIdentity = t.mock('../../../lib/utils/get-identity.js', {
     'npm-registry-fetch': {
       json: (path, opts) => {
         t.equal(path, '/-/whoami', 'calls whoami')
@@ -86,9 +85,9 @@ test('throws ENEEDAUTH when response does not include a username', async (t) =>
   }
 })
 
-test('throws ENEEDAUTH when neither username nor token is configured', async (t) => {
+t.test('throws ENEEDAUTH when neither username nor token is configured', async (t) => {
   t.plan(1)
-  const getIdentity = requireInject('../../../lib/utils/get-identity.js', {
+  const getIdentity = t.mock('../../../lib/utils/get-identity.js', {
   })
   const npm = {
     config: {
diff --git a/test/lib/utils/npm-usage.js b/test/lib/utils/npm-usage.js
index ebf637ae1cfb7..f846a01109d2f 100644
--- a/test/lib/utils/npm-usage.js
+++ b/test/lib/utils/npm-usage.js
@@ -2,11 +2,10 @@ const t = require('tap')
 const npm = require('../../../lib/npm.js')
 
 t.test('usage', t => {
-  t.afterEach((cb) => {
+  t.afterEach(() => {
     npm.config.set('viewer', null)
     npm.config.set('long', false)
     npm.config.set('userconfig', '/some/config/file/.npmrc')
-    cb()
   })
   const { dirname } = require('path')
   const basedir = dirname(dirname(dirname(__dirname)))
diff --git a/test/lib/utils/open-url.js b/test/lib/utils/open-url.js
index 781b70d3e8d31..a31a8cb6867df 100644
--- a/test/lib/utils/open-url.js
+++ b/test/lib/utils/open-url.js
@@ -1,5 +1,4 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 
 const OUTPUT = []
 const output = (...args) => OUTPUT.push(args)
@@ -26,11 +25,11 @@ const opener = (url, opts, cb) => {
   return cb(openerResult)
 }
 
-const openUrl = requireInject('../../../lib/utils/open-url.js', {
+const openUrl = t.mock('../../../lib/utils/open-url.js', {
   opener,
 })
 
-test('opens a url', async (t) => {
+t.test('opens a url', async (t) => {
   t.teardown(() => {
     openerUrl = null
     openerOpts = null
@@ -42,7 +41,7 @@ test('opens a url', async (t) => {
   t.same(OUTPUT, [], 'printed no output')
 })
 
-test('returns error for non-https and non-file url', async (t) => {
+t.test('returns error for non-https and non-file url', async (t) => {
   t.teardown(() => {
     openerUrl = null
     openerOpts = null
@@ -52,10 +51,10 @@ test('returns error for non-https and non-file url', async (t) => {
   t.equal(openerUrl, null, 'did not open')
   t.same(openerOpts, null, 'did not open')
   t.same(OUTPUT, [], 'printed no output')
-  t.done()
+  t.end()
 })
 
-test('returns error for non-parseable url', async (t) => {
+t.test('returns error for non-parseable url', async (t) => {
   t.teardown(() => {
     openerUrl = null
     openerOpts = null
@@ -65,10 +64,10 @@ test('returns error for non-parseable url', async (t) => {
   t.equal(openerUrl, null, 'did not open')
   t.same(openerOpts, null, 'did not open')
   t.same(OUTPUT, [], 'printed no output')
-  t.done()
+  t.end()
 })
 
-test('opens a url with the given browser', async (t) => {
+t.test('opens a url with the given browser', async (t) => {
   npm.config.set('browser', 'chrome')
   t.teardown(() => {
     openerUrl = null
@@ -80,10 +79,10 @@ test('opens a url with the given browser', async (t) => {
   t.equal(openerUrl, 'https://www.npmjs.com', 'opened the given url')
   t.same(openerOpts, { command: 'chrome' }, 'passed the given browser as command')
   t.same(OUTPUT, [], 'printed no output')
-  t.done()
+  t.end()
 })
 
-test('prints where to go when browser is disabled', async (t) => {
+t.test('prints where to go when browser is disabled', async (t) => {
   npm.config.set('browser', false)
   t.teardown(() => {
     openerUrl = null
@@ -97,10 +96,10 @@ test('prints where to go when browser is disabled', async (t) => {
   t.equal(OUTPUT.length, 1, 'got one logged message')
   t.equal(OUTPUT[0].length, 1, 'logged message had one value')
   t.matchSnapshot(OUTPUT[0][0], 'printed expected message')
-  t.done()
+  t.end()
 })
 
-test('prints where to go when browser is disabled and json is enabled', async (t) => {
+t.test('prints where to go when browser is disabled and json is enabled', async (t) => {
   npm.config.set('browser', false)
   npm.config.set('json', true)
   t.teardown(() => {
@@ -116,10 +115,10 @@ test('prints where to go when browser is disabled and json is enabled', async (t
   t.equal(OUTPUT.length, 1, 'got one logged message')
   t.equal(OUTPUT[0].length, 1, 'logged message had one value')
   t.matchSnapshot(OUTPUT[0][0], 'printed expected message')
-  t.done()
+  t.end()
 })
 
-test('prints where to go when given browser does not exist', async (t) => {
+t.test('prints where to go when given browser does not exist', async (t) => {
   npm.config.set('browser', 'firefox')
   openerResult = Object.assign(new Error('failed'), { code: 'ENOENT' })
   t.teardown(() => {
@@ -134,10 +133,10 @@ test('prints where to go when given browser does not exist', async (t) => {
   t.equal(OUTPUT.length, 1, 'got one logged message')
   t.equal(OUTPUT[0].length, 1, 'logged message had one value')
   t.matchSnapshot(OUTPUT[0][0], 'printed expected message')
-  t.done()
+  t.end()
 })
 
-test('handles unknown opener error', async (t) => {
+t.test('handles unknown opener error', async (t) => {
   npm.config.set('browser', 'firefox')
   openerResult = Object.assign(new Error('failed'), { code: 'ENOBRIAN' })
   t.teardown(() => {
@@ -147,5 +146,5 @@ test('handles unknown opener error', async (t) => {
     npm.config.set('browser', true)
   })
   t.rejects(openUrl(npm, 'https://www.npmjs.com', 'npm home'), 'failed', 'got the correct error')
-  t.done()
+  t.end()
 })
diff --git a/test/lib/utils/otplease.js b/test/lib/utils/otplease.js
index 048856b485770..fb9476120e2df 100644
--- a/test/lib/utils/otplease.js
+++ b/test/lib/utils/otplease.js
@@ -1,15 +1,14 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 
 const readUserInfo = {
   otp: async () => '1234',
 }
 
-const otplease = requireInject('../../../lib/utils/otplease.js', {
+const otplease = t.mock('../../../lib/utils/otplease.js', {
   '../../../lib/utils/read-user-info.js': readUserInfo,
 })
 
-test('prompts for otp for EOTP', async (t) => {
+t.test('prompts for otp for EOTP', async (t) => {
   const stdinTTY = process.stdin.isTTY
   const stdoutTTY = process.stdout.isTTY
   process.stdin.isTTY = true
@@ -26,13 +25,13 @@ test('prompts for otp for EOTP', async (t) => {
 
     t.equal(opts.some, 'prop', 'carried original options')
     t.equal(opts.otp, '1234', 'received the otp')
-    t.done()
+    t.end()
   }
 
   await otplease({ some: 'prop' }, fn)
 })
 
-test('prompts for otp for 401', async (t) => {
+t.test('prompts for otp for 401', async (t) => {
   const stdinTTY = process.stdin.isTTY
   const stdoutTTY = process.stdout.isTTY
   process.stdin.isTTY = true
@@ -53,13 +52,13 @@ test('prompts for otp for 401', async (t) => {
 
     t.equal(opts.some, 'prop', 'carried original options')
     t.equal(opts.otp, '1234', 'received the otp')
-    t.done()
+    t.end()
   }
 
   await otplease({ some: 'prop' }, fn)
 })
 
-test('does not prompt for non-otp errors', async (t) => {
+t.test('does not prompt for non-otp errors', async (t) => {
   const stdinTTY = process.stdin.isTTY
   const stdoutTTY = process.stdout.isTTY
   process.stdin.isTTY = true
@@ -76,7 +75,7 @@ test('does not prompt for non-otp errors', async (t) => {
   t.rejects(otplease({ some: 'prop' }, fn), { message: 'nope' }, 'rejects with the original error')
 })
 
-test('does not prompt if stdin or stdout is not a tty', async (t) => {
+t.test('does not prompt if stdin or stdout is not a tty', async (t) => {
   const stdinTTY = process.stdin.isTTY
   const stdoutTTY = process.stdout.isTTY
   process.stdin.isTTY = false
diff --git a/test/lib/utils/path.js b/test/lib/utils/path.js
index 74fb93462f755..0a7846d94bc67 100644
--- a/test/lib/utils/path.js
+++ b/test/lib/utils/path.js
@@ -1,13 +1,12 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const mod = '../../../lib/utils/path.js'
 const delim = require('../../../lib/utils/is-windows.js') ? ';' : ':'
 Object.defineProperty(process, 'env', {
   value: {},
 })
 process.env.path = ['foo', 'bar', 'baz'].join(delim)
-t.strictSame(requireInject(mod), ['foo', 'bar', 'baz'])
+t.strictSame(t.mock(mod), ['foo', 'bar', 'baz'])
 process.env.Path = ['a', 'b', 'c'].join(delim)
-t.strictSame(requireInject(mod), ['a', 'b', 'c'])
+t.strictSame(t.mock(mod), ['a', 'b', 'c'])
 process.env.PATH = ['x', 'y', 'z'].join(delim)
-t.strictSame(requireInject(mod), ['x', 'y', 'z'])
+t.strictSame(t.mock(mod), ['x', 'y', 'z'])
diff --git a/test/lib/utils/ping.js b/test/lib/utils/ping.js
index 6e0451538f9fa..1bebfa69d2b78 100644
--- a/test/lib/utils/ping.js
+++ b/test/lib/utils/ping.js
@@ -1,12 +1,11 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 
-test('pings', async (t) => {
+t.test('pings', async (t) => {
   t.plan(3)
 
   const options = { fake: 'options' }
   const response = { some: 'details' }
-  const ping = requireInject('../../../lib/utils/ping.js', {
+  const ping = t.mock('../../../lib/utils/ping.js', {
     'npm-registry-fetch': (url, opts) => {
       t.equal(url, '/-/ping?write=true', 'calls the correct url')
       t.equal(opts, options, 'passes through options')
@@ -18,12 +17,12 @@ test('pings', async (t) => {
   t.match(res, response, 'returns json response')
 })
 
-test('catches errors and returns empty json', async (t) => {
+t.test('catches errors and returns empty json', async (t) => {
   t.plan(3)
 
   const options = { fake: 'options' }
   const response = { some: 'details' }
-  const ping = requireInject('../../../lib/utils/ping.js', {
+  const ping = t.mock('../../../lib/utils/ping.js', {
     'npm-registry-fetch': (url, opts) => {
       t.equal(url, '/-/ping?write=true', 'calls the correct url')
       t.equal(opts, options, 'passes through options')
diff --git a/test/lib/utils/proc-log-listener.js b/test/lib/utils/proc-log-listener.js
index 2c1009503762d..d580defa8a98f 100644
--- a/test/lib/utils/proc-log-listener.js
+++ b/test/lib/utils/proc-log-listener.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const { inspect } = require('util')
 
 const logs = []
@@ -8,7 +7,7 @@ const npmlog = {
   verbose: (...args) => logs.push(['verbose', ...args]),
 }
 
-requireInject('../../../lib/utils/proc-log-listener.js', {
+t.mock('../../../lib/utils/proc-log-listener.js', {
   npmlog,
 })()
 
diff --git a/test/lib/utils/pulse-till-done.js b/test/lib/utils/pulse-till-done.js
index 16c2d521dad08..c1d7902c0684a 100644
--- a/test/lib/utils/pulse-till-done.js
+++ b/test/lib/utils/pulse-till-done.js
@@ -1,5 +1,4 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 
 let pulseStarted = null
 const npmlog = {
@@ -11,11 +10,11 @@ const npmlog = {
   },
 }
 
-const pulseTillDone = requireInject('../../../lib/utils/pulse-till-done.js', {
+const pulseTillDone = t.mock('../../../lib/utils/pulse-till-done.js', {
   npmlog,
 })
 
-test('pulses (with promise)', async (t) => {
+t.test('pulses (with promise)', async (t) => {
   t.teardown(() => {
     pulseStarted = null
   })
diff --git a/test/lib/utils/read-local-package.js b/test/lib/utils/read-local-package.js
index 4b693afb48b8e..966e74a7ab7f4 100644
--- a/test/lib/utils/read-local-package.js
+++ b/test/lib/utils/read-local-package.js
@@ -1,5 +1,4 @@
-const requireInject = require('require-inject')
-const { test } = require('tap')
+const t = require('tap')
 const mockNpm = require('../../fixtures/mock-npm')
 
 const config = {
@@ -8,9 +7,9 @@ const config = {
 }
 const npm = mockNpm({ config })
 
-const readLocalPackageName = requireInject('../../../lib/utils/read-local-package.js')
+const readLocalPackageName = require('../../../lib/utils/read-local-package.js')
 
-test('read local package.json', async (t) => {
+t.test('read local package.json', async (t) => {
   npm.prefix = t.testdir({
     'package.json': JSON.stringify({
       name: 'my-local-package',
@@ -25,7 +24,7 @@ test('read local package.json', async (t) => {
   )
 })
 
-test('read local scoped-package.json', async (t) => {
+t.test('read local scoped-package.json', async (t) => {
   npm.prefix = t.testdir({
     'package.json': JSON.stringify({
       name: '@my-scope/my-local-package',
@@ -40,7 +39,7 @@ test('read local scoped-package.json', async (t) => {
   )
 })
 
-test('read using --global', async (t) => {
+t.test('read using --global', async (t) => {
   npm.prefix = t.testdir({})
   config.global = true
   const packageName = await readLocalPackageName(npm)
diff --git a/test/lib/utils/read-user-info.js b/test/lib/utils/read-user-info.js
index 99d85d66c4feb..5d937ff78a551 100644
--- a/test/lib/utils/read-user-info.js
+++ b/test/lib/utils/read-user-info.js
@@ -1,5 +1,4 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 
 let readOpts = null
 let readResult = null
@@ -28,13 +27,13 @@ const npmUserValidate = {
   },
 }
 
-const readUserInfo = requireInject('../../../lib/utils/read-user-info.js', {
+const readUserInfo = t.mock('../../../lib/utils/read-user-info.js', {
   read,
   npmlog,
   'npm-user-validate': npmUserValidate,
 })
 
-test('otp', async (t) => {
+t.test('otp', async (t) => {
   readResult = '1234'
   t.teardown(() => {
     readResult = null
@@ -44,7 +43,7 @@ test('otp', async (t) => {
   t.equal(result, '1234', 'received the otp')
 })
 
-test('password', async (t) => {
+t.test('password', async (t) => {
   readResult = 'password'
   t.teardown(() => {
     readResult = null
@@ -57,7 +56,7 @@ test('password', async (t) => {
   }, 'got the correct options')
 })
 
-test('username', async (t) => {
+t.test('username', async (t) => {
   readResult = 'username'
   t.teardown(() => {
     readResult = null
@@ -67,7 +66,7 @@ test('username', async (t) => {
   t.equal(result, 'username', 'received the username')
 })
 
-test('username - invalid warns and retries', async (t) => {
+t.test('username - invalid warns and retries', async (t) => {
   readResult = 'invalid'
   t.teardown(() => {
     readResult = null
@@ -87,7 +86,7 @@ test('username - invalid warns and retries', async (t) => {
   t.equal(logMsg, 'invalid username')
 })
 
-test('email', async (t) => {
+t.test('email', async (t) => {
   readResult = 'foo@bar.baz'
   t.teardown(() => {
     readResult = null
@@ -97,7 +96,7 @@ test('email', async (t) => {
   t.equal(result, 'foo@bar.baz', 'received the email')
 })
 
-test('email - invalid warns and retries', async (t) => {
+t.test('email - invalid warns and retries', async (t) => {
   readResult = 'invalid@bar.baz'
   t.teardown(() => {
     readResult = null
diff --git a/test/lib/utils/reify-finish.js b/test/lib/utils/reify-finish.js
index 7ff5146a6bdbf..bbe8a3d99021d 100644
--- a/test/lib/utils/reify-finish.js
+++ b/test/lib/utils/reify-finish.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 
 const npm = {
   config: {
@@ -30,7 +29,7 @@ const fs = {
   },
 }
 
-const reifyFinish = requireInject('../../../lib/utils/reify-finish.js', {
+const reifyFinish = t.mock('../../../lib/utils/reify-finish.js', {
   fs,
   '../../../lib/utils/reify-output.js': reifyOutput,
 })
@@ -79,7 +78,7 @@ t.test('should write if everything above passes', async t => {
 })
 
 t.test('works without fs.promises', async t => {
-  t.doesNotThrow(() => requireInject('../../../lib/utils/reify-finish.js', {
+  t.doesNotThrow(() => t.mock('../../../lib/utils/reify-finish.js', {
     fs: { ...fs, promises: null },
     '../../../lib/npm.js': npm,
     '../../../lib/utils/reify-output.js': reifyOutput,
diff --git a/test/lib/utils/reify-output.js b/test/lib/utils/reify-output.js
index e4f58b4668e05..2142566b90dea 100644
--- a/test/lib/utils/reify-output.js
+++ b/test/lib/utils/reify-output.js
@@ -15,7 +15,7 @@ const npm = {
 const reifyOutput = require('../../../lib/utils/reify-output.js')
 t.test('missing info', (t) => {
   t.plan(1)
-  npm.output = out => t.doesNotHave(
+  npm.output = out => t.notMatch(
     out,
     'looking for funding',
     'should not print fund message if missing info'
@@ -33,7 +33,7 @@ t.test('missing info', (t) => {
 
 t.test('even more missing info', t => {
   t.plan(1)
-  npm.output = out => t.doesNotHave(
+  npm.output = out => t.notMatch(
     out,
     'looking for funding',
     'should not print fund message if missing info'
diff --git a/test/lib/utils/replace-info.js b/test/lib/utils/replace-info.js
index ea9f06520d0a7..e4b83783a55a7 100644
--- a/test/lib/utils/replace-info.js
+++ b/test/lib/utils/replace-info.js
@@ -49,7 +49,7 @@ t.equal(
   'should replace single item within a phrase'
 )
 
-t.deepEqual(
+t.same(
   replaceInfo([
     'Something https://user:pass@registry.npmjs.org/ foo bar',
     'http://foo:bar@registry.npmjs.org',
@@ -63,7 +63,7 @@ t.deepEqual(
   'should replace single item within a phrase'
 )
 
-t.deepEqual(
+t.same(
   replaceInfo([
     'Something https://user:pass@registry.npmjs.org/ foo bar',
     null,
diff --git a/test/lib/utils/setup-log.js b/test/lib/utils/setup-log.js
index 4398200abe22c..3daf3b8a52f53 100644
--- a/test/lib/utils/setup-log.js
+++ b/test/lib/utils/setup-log.js
@@ -1,14 +1,12 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 
 const settings = {
   level: 'warn',
 }
-t.afterEach(cb => {
+t.afterEach(() => {
   Object.keys(settings).forEach(k => {
     delete settings[k]
   })
-  cb()
 })
 
 const WARN_CALLED = []
@@ -61,7 +59,7 @@ const npmlog = {
 }
 
 const EXPLAIN_CALLED = []
-const setupLog = requireInject('../../../lib/utils/setup-log.js', {
+const setupLog = t.mock('../../../lib/utils/setup-log.js', {
   '../../../lib/utils/explain-eresolve.js': {
     explain: (...args) => {
       EXPLAIN_CALLED.push(args)
diff --git a/test/lib/utils/split-package-names.js b/test/lib/utils/split-package-names.js
index c69bb2a3dab8c..82b8f5578397f 100644
--- a/test/lib/utils/split-package-names.js
+++ b/test/lib/utils/split-package-names.js
@@ -1,9 +1,9 @@
 'use strict'
 
-const { test } = require('tap')
+const t = require('tap')
 const splitPackageNames = require('../../../lib/utils/split-package-names.js')
 
-test('splitPackageNames', t => {
+t.test('splitPackageNames', t => {
   const assertions = [
     ['semver', 'semver'],
     ['read-pkg/semver', 'read-pkg/node_modules/semver'],
diff --git a/test/lib/utils/tar.js b/test/lib/utils/tar.js
index d9b8c5584a61b..5758442fcb6f6 100644
--- a/test/lib/utils/tar.js
+++ b/test/lib/utils/tar.js
@@ -1,7 +1,6 @@
-const { test } = require('tap')
+const t = require('tap')
 const pack = require('libnpmpack')
 const ssri = require('ssri')
-const requireInject = require('require-inject')
 
 const { logTar, getContents } = require('../../../lib/utils/tar.js')
 
@@ -18,7 +17,7 @@ const printLogs = (tarball, unicode) => {
   return logs.join('\n')
 }
 
-test('should log tarball contents', async (t) => {
+t.test('should log tarball contents', async (t) => {
   const testDir = t.testdir({
     'package.json': JSON.stringify({
       name: 'my-cool-pkg',
@@ -42,8 +41,8 @@ test('should log tarball contents', async (t) => {
   t.matchSnapshot(printLogs(tarballContents, false))
 })
 
-test('should log tarball contents with unicode', async (t) => {
-  const { logTar } = requireInject('../../../lib/utils/tar.js', {
+t.test('should log tarball contents with unicode', async (t) => {
+  const { logTar } = t.mock('../../../lib/utils/tar.js', {
     npmlog: {
       notice: (str) => {
         t.ok(true, 'defaults to npmlog')
@@ -60,8 +59,8 @@ test('should log tarball contents with unicode', async (t) => {
   t.end()
 })
 
-test('should default to npmlog', async (t) => {
-  const { logTar } = requireInject('../../../lib/utils/tar.js', {
+t.test('should default to npmlog', async (t) => {
+  const { logTar } = t.mock('../../../lib/utils/tar.js', {
     npmlog: {
       notice: (str) => {
         t.ok(true, 'defaults to npmlog')
@@ -78,7 +77,7 @@ test('should default to npmlog', async (t) => {
   t.end()
 })
 
-test('should getContents of a tarball', async (t) => {
+t.test('should getContents of a tarball', async (t) => {
   const testDir = t.testdir({
     'package.json': JSON.stringify({
       name: 'my-cool-pkg',
diff --git a/test/lib/utils/unsupported.js b/test/lib/utils/unsupported.js
index f14cba9b744ad..3a05d90666025 100644
--- a/test/lib/utils/unsupported.js
+++ b/test/lib/utils/unsupported.js
@@ -1,4 +1,4 @@
-const test = require('tap').test
+const t = require('tap')
 const unsupported = require('../../../lib/utils/unsupported.js')
 
 const versions = [
@@ -33,20 +33,20 @@ const versions = [
   ['v13.0.0-0', false, false],
 ]
 
-test('versions', function (t) {
+t.test('versions', function (t) {
   t.plan(versions.length * 2)
   versions.forEach(function (verinfo) {
     const version = verinfo[0]
     const broken = verinfo[1]
     const unsupp = verinfo[2]
     const nodejs = unsupported.checkVersion(version)
-    t.is(nodejs.broken, broken, version + ' ' + (broken ? '' : 'not ') + 'broken')
-    t.is(nodejs.unsupported, unsupp, version + ' ' + (unsupp ? 'unsupported' : 'supported'))
+    t.equal(nodejs.broken, broken, version + ' ' + (broken ? '' : 'not ') + 'broken')
+    t.equal(nodejs.unsupported, unsupp, version + ' ' + (unsupp ? 'unsupported' : 'supported'))
   })
-  t.done()
+  t.end()
 })
 
-test('checkForBrokenNode', t => {
+t.test('checkForBrokenNode', t => {
   // run it once to not fail
   unsupported.checkForBrokenNode()
 
@@ -77,7 +77,7 @@ test('checkForBrokenNode', t => {
   unsupported.checkForBrokenNode()
 })
 
-test('checkForUnsupportedNode', t => {
+t.test('checkForUnsupportedNode', t => {
   const npmlog = require('npmlog')
   const { warn } = npmlog
   const versionPropDesc = Object.getOwnPropertyDescriptor(process, 'version')
diff --git a/test/lib/utils/update-notifier.js b/test/lib/utils/update-notifier.js
index 99c9dfc26626f..1735b31057b14 100644
--- a/test/lib/utils/update-notifier.js
+++ b/test/lib/utils/update-notifier.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 let ciMock = null
 const flatOptions = { global: false, cache: t.testdir() + '/_cacache' }
 
@@ -52,6 +51,7 @@ let STAT_ERROR = null
 let STAT_MTIME = null
 let WRITE_ERROR = null
 const fs = {
+  ...require('fs'),
   stat: (path, cb) => {
     if (basename(path) !== '_update-notifier-last-checked') {
       console.error(new Error('should only write to notifier last checked file'))
@@ -72,19 +72,18 @@ const fs = {
   },
 }
 
-const updateNotifier = requireInject('../../../lib/utils/update-notifier.js', {
+const updateNotifier = t.mock('../../../lib/utils/update-notifier.js', {
   '@npmcli/ci-detect': () => ciMock,
   pacote,
   fs,
 })
 
-t.afterEach(cb => {
+t.afterEach(() => {
   MANIFEST_REQUEST.length = 0
   STAT_ERROR = null
   PACOTE_ERROR = null
   STAT_MTIME = null
   WRITE_ERROR = null
-  cb()
 })
 
 t.test('situations in which we do not notify', t => {
diff --git a/test/lib/version.js b/test/lib/version.js
index 35d3d92cd2bee..9cd5f47a0e55f 100644
--- a/test/lib/version.js
+++ b/test/lib/version.js
@@ -1,5 +1,4 @@
 const t = require('tap')
-const requireInject = require('require-inject')
 const mockNpm = require('../fixtures/mock-npm')
 
 let result = []
@@ -22,16 +21,15 @@ const mocks = {
   libnpmversion: noop,
 }
 
-const Version = requireInject('../../lib/version.js', mocks)
+const Version = t.mock('../../lib/version.js', mocks)
 const version = new Version(npm)
 
 const _processVersions = process.versions
-t.afterEach(cb => {
+t.afterEach(() => {
   config.json = false
   npm.prefix = ''
   process.versions = _processVersions
   result = []
-  cb()
 })
 
 t.test('no args', t => {
@@ -48,7 +46,7 @@ t.test('no args', t => {
     if (err)
       throw err
 
-    t.deepEqual(
+    t.same(
       result,
       [{
         'test-version-no-args': '3.2.1',
@@ -103,7 +101,7 @@ t.test('failure reading package.json', t => {
     if (err)
       throw err
 
-    t.deepEqual(
+    t.same(
       result,
       [{
         npm: '1.0.0',
@@ -125,7 +123,7 @@ t.test('--json option', t => {
   version.exec([], err => {
     if (err)
       throw err
-    t.deepEqual(
+    t.same(
       result,
       ['{\n  "npm": "1.0.0"\n}'],
       'should return json stringified result'
@@ -135,11 +133,11 @@ t.test('--json option', t => {
 })
 
 t.test('with one arg', t => {
-  const Version = requireInject('../../lib/version.js', {
+  const Version = t.mock('../../lib/version.js', {
     ...mocks,
     libnpmversion: (arg, opts) => {
       t.equal(arg, 'major', 'should forward expected value')
-      t.deepEqual(
+      t.same(
         opts,
         {
           path: '',
diff --git a/test/lib/view.js b/test/lib/view.js
index 91ce18786b218..eb2beb9ff5864 100644
--- a/test/lib/view.js
+++ b/test/lib/view.js
@@ -1,16 +1,18 @@
 const t = require('tap')
-const requireInject = require('require-inject')
+
+// run the same as tap does when running directly with node
+process.stdout.columns = undefined
+
 const mockNpm = require('../fixtures/mock-npm')
 
 let logs
-const cleanLogs = (done) => {
+const cleanLogs = () => {
   logs = ''
   const fn = (...args) => {
     logs += '\n'
     args.map(el => logs += el)
   }
   console.log = fn
-  done()
 }
 
 const packument = (nv, opts) => {
@@ -240,7 +242,7 @@ const packument = (nv, opts) => {
 t.beforeEach(cleanLogs)
 
 t.test('should log package info', t => {
-  const View = requireInject('../../lib/view.js', {
+  const View = t.mock('../../lib/view.js', {
     pacote: {
       packument,
     },
@@ -250,7 +252,7 @@ t.test('should log package info', t => {
   })
   const view = new View(npm)
 
-  const ViewJson = requireInject('../../lib/view.js', {
+  const ViewJson = t.mock('../../lib/view.js', {
     pacote: {
       packument,
     },
@@ -260,7 +262,7 @@ t.test('should log package info', t => {
   })
   const viewJson = new ViewJson(jsonNpm)
 
-  const ViewUnicode = requireInject('../../lib/view.js', {
+  const ViewUnicode = t.mock('../../lib/view.js', {
     pacote: {
       packument,
     },
@@ -303,7 +305,7 @@ t.test('should log package info', t => {
 
   t.test('package with no versions', t => {
     view.exec(['brown'], () => {
-      t.equals(logs, '', 'no info to display')
+      t.equal(logs, '', 'no info to display')
       t.end()
     })
   })
@@ -331,7 +333,7 @@ t.test('should log package info', t => {
 
   t.test('package with --json and no versions', t => {
     viewJson.exec(['brown'], () => {
-      t.equals(logs, '', 'no info to display')
+      t.equal(logs, '', 'no info to display')
       t.end()
     })
   })
@@ -347,7 +349,7 @@ t.test('should log info of package in current working dir', t => {
     }, null, 2),
   })
 
-  const View = requireInject('../../lib/view.js', {
+  const View = t.mock('../../lib/view.js', {
     pacote: {
       packument,
     },
@@ -379,7 +381,7 @@ t.test('should log info of package in current working dir', t => {
 })
 
 t.test('should log info by field name', t => {
-  const ViewJson = requireInject('../../lib/view.js', {
+  const ViewJson = t.mock('../../lib/view.js', {
     pacote: {
       packument,
     },
@@ -393,7 +395,7 @@ t.test('should log info by field name', t => {
 
   const viewJson = new ViewJson(jsonNpm)
 
-  const View = requireInject('../../lib/view.js', {
+  const View = t.mock('../../lib/view.js', {
     pacote: {
       packument,
     },
@@ -447,7 +449,7 @@ t.test('should log info by field name', t => {
 
   t.test('unknown nested field ', t => {
     view.exec(['yellow@1.0.0', 'dist.foobar'], () => {
-      t.equals(logs, '', 'no info to display')
+      t.equal(logs, '', 'no info to display')
       t.end()
     })
   })
@@ -470,13 +472,13 @@ t.test('should log info by field name', t => {
 })
 
 t.test('throw error if global mode', (t) => {
-  const View = requireInject('../../lib/view.js')
+  const View = t.mock('../../lib/view.js')
   const npm = mockNpm({
     config: { global: true },
   })
   const view = new View(npm)
   view.exec([], (err) => {
-    t.equals(err.message, 'Cannot use view command in global mode.')
+    t.equal(err.message, 'Cannot use view command in global mode.')
     t.end()
   })
 })
@@ -484,7 +486,7 @@ t.test('throw error if global mode', (t) => {
 t.test('throw ENOENT error if package.json misisng', (t) => {
   const testDir = t.testdir({})
 
-  const View = requireInject('../../lib/view.js')
+  const View = t.mock('../../lib/view.js')
   const npm = mockNpm({
     prefix: testDir,
     config: { global: false },
@@ -501,7 +503,7 @@ t.test('throw EJSONPARSE error if package.json not json', (t) => {
     'package.json': 'not json, nope, not even a little bit!',
   })
 
-  const View = requireInject('../../lib/view.js')
+  const View = t.mock('../../lib/view.js')
   const npm = mockNpm({
     prefix: testDir,
     config: { global: false },
@@ -518,20 +520,20 @@ t.test('throw error if package.json has no name', (t) => {
     'package.json': '{}',
   })
 
-  const View = requireInject('../../lib/view.js')
+  const View = t.mock('../../lib/view.js')
   const npm = mockNpm({
     prefix: testDir,
     config: { global: false },
   })
   const view = new View(npm)
   view.exec([], (err) => {
-    t.equals(err.message, 'Invalid package.json, no "name" field')
+    t.equal(err.message, 'Invalid package.json, no "name" field')
     t.end()
   })
 })
 
 t.test('throws when unpublished', (t) => {
-  const View = requireInject('../../lib/view.js', {
+  const View = t.mock('../../lib/view.js', {
     pacote: {
       packument,
     },
@@ -544,16 +546,15 @@ t.test('throws when unpublished', (t) => {
   })
   const view = new View(npm)
   view.exec(['red'], (err) => {
-    t.equals(err.code, 'E404')
+    t.equal(err.code, 'E404')
     t.end()
   })
 })
 
 t.test('workspaces', t => {
-  t.beforeEach((done) => {
+  t.beforeEach(() => {
     warnMsg = undefined
     config.json = false
-    done()
   })
   const testDir = t.testdir({
     'package.json': JSON.stringify({
@@ -574,7 +575,7 @@ t.test('workspaces', t => {
       }),
     },
   })
-  const View = requireInject('../../lib/view.js', {
+  const View = t.mock('../../lib/view.js', {
     pacote: {
       packument,
     },
@@ -675,7 +676,7 @@ t.test('workspaces', t => {
 })
 
 t.test('completion', async t => {
-  const View = requireInject('../../lib/view.js', {
+  const View = t.mock('../../lib/view.js', {
     pacote: {
       packument,
     },
@@ -695,7 +696,7 @@ t.test('completion', async t => {
 })
 
 t.test('no registry completion', async t => {
-  const View = requireInject('../../lib/view.js')
+  const View = t.mock('../../lib/view.js')
   const npm = mockNpm({
     config: {
       tag: '1.0.1',
diff --git a/test/lib/whoami.js b/test/lib/whoami.js
index b242ea8941478..5e350a32ebfb4 100644
--- a/test/lib/whoami.js
+++ b/test/lib/whoami.js
@@ -1,10 +1,9 @@
-const { test } = require('tap')
-const requireInject = require('require-inject')
+const t = require('tap')
 const mockNpm = require('../fixtures/mock-npm')
 
-test('whoami', (t) => {
+t.test('whoami', (t) => {
   t.plan(3)
-  const Whoami = requireInject('../../lib/whoami.js', {
+  const Whoami = t.mock('../../lib/whoami.js', {
     '../../lib/utils/get-identity.js': () => Promise.resolve('foo'),
   })
   const npm = mockNpm({
@@ -17,14 +16,14 @@ test('whoami', (t) => {
   const whoami = new Whoami(npm)
 
   whoami.exec([], (err) => {
-    t.ifError(err, 'npm whoami')
+    t.error(err, 'npm whoami')
     t.ok('should successfully print username')
   })
 })
 
-test('whoami json', (t) => {
+t.test('whoami json', (t) => {
   t.plan(3)
-  const Whoami = requireInject('../../lib/whoami.js', {
+  const Whoami = t.mock('../../lib/whoami.js', {
     '../../lib/utils/get-identity.js': () => Promise.resolve('foo'),
   })
   const npm = mockNpm({
@@ -36,7 +35,7 @@ test('whoami json', (t) => {
   const whoami = new Whoami(npm)
 
   whoami.exec([], (err) => {
-    t.ifError(err, 'npm whoami')
+    t.error(err, 'npm whoami')
     t.ok('should successfully print username as json')
   })
 })
diff --git a/test/lib/workspaces/get-workspaces.js b/test/lib/workspaces/get-workspaces.js
index ebed9dd35c519..4ea055e02f8f2 100644
--- a/test/lib/workspaces/get-workspaces.js
+++ b/test/lib/workspaces/get-workspaces.js
@@ -77,7 +77,7 @@ t.test('get-workspaces', async t => {
   let workspaces
 
   workspaces = await getWorkspaces(['a', 'b'], { path })
-  t.deepEqual(
+  t.same(
     clean(workspaces, path),
     new Map(Object.entries({
       a: '{PATH}/packages/a',
@@ -87,7 +87,7 @@ t.test('get-workspaces', async t => {
   )
 
   workspaces = await getWorkspaces(['./packages/c'], { path })
-  t.deepEqual(
+  t.same(
     clean(workspaces, path),
     new Map(Object.entries({
       c: '{PATH}/packages/c',
@@ -96,7 +96,7 @@ t.test('get-workspaces', async t => {
   )
 
   workspaces = await getWorkspaces(['packages/c'], { path })
-  t.deepEqual(
+  t.same(
     clean(workspaces, path),
     new Map(Object.entries({
       c: '{PATH}/packages/c',
@@ -105,7 +105,7 @@ t.test('get-workspaces', async t => {
   )
 
   workspaces = await getWorkspaces([resolve(path, 'packages/c')], { path })
-  t.deepEqual(
+  t.same(
     clean(workspaces, path),
     new Map(Object.entries({
       c: '{PATH}/packages/c',
@@ -114,7 +114,7 @@ t.test('get-workspaces', async t => {
   )
 
   workspaces = await getWorkspaces(['packages'], { path })
-  t.deepEqual(
+  t.same(
     clean(workspaces, path),
     new Map(Object.entries({
       a: '{PATH}/packages/a',
@@ -128,7 +128,7 @@ t.test('get-workspaces', async t => {
   )
 
   workspaces = await getWorkspaces(['./packages/'], { path })
-  t.deepEqual(
+  t.same(
     clean(workspaces, path),
     new Map(Object.entries({
       a: '{PATH}/packages/a',
@@ -142,7 +142,7 @@ t.test('get-workspaces', async t => {
   )
 
   workspaces = await getWorkspaces([resolve(path, './packages')], { path })
-  t.deepEqual(
+  t.same(
     clean(workspaces, path),
     new Map(Object.entries({
       a: '{PATH}/packages/a',
@@ -156,7 +156,7 @@ t.test('get-workspaces', async t => {
   )
 
   workspaces = await getWorkspaces([], { path })
-  t.deepEqual(
+  t.same(
     clean(workspaces, path),
     new Map(Object.entries({
       a: '{PATH}/packages/a',