diff --git a/CHANGELOG.md b/CHANGELOG.md index 811c9fde335c..07c630555d7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,13 @@ ### Features - `[@jest/globals]` New package so Jest's globals can be explicitly imported ([#9801](https://github.com/facebook/jest/pull/9801)) +- `[jest-core]` Show coverage of sources related to tests in changed files ([#9769](https://github.com/facebook/jest/pull/9769)) - `[jest-runtime]` Populate `require.cache` ([#9841](https://github.com/facebook/jest/pull/9841)) ### Fixes +- `[expect]` Prints the Symbol name into the error message with a custom asymmetric matcher ([#9888](https://github.com/facebook/jest/pull/9888)) +- `[@jest/environment]` Make sure not to reference Jest types ([#9875](https://github.com/facebook/jest/pull/9875)) - `[jest-message-util]` Code frame printing should respect `--noStackTrace` flag ([#9866](https://github.com/facebook/jest/pull/9866)) - `[jest-runtime]` Support importing CJS from ESM using `import` statements ([#9850](https://github.com/facebook/jest/pull/9850)) - `[jest-runtime]` Support importing parallel dynamic `import`s ([#9858](https://github.com/facebook/jest/pull/9858)) diff --git a/e2e/__tests__/onlyChanged.test.ts b/e2e/__tests__/onlyChanged.test.ts index 52abdd6d0613..947a11d50ddc 100644 --- a/e2e/__tests__/onlyChanged.test.ts +++ b/e2e/__tests__/onlyChanged.test.ts @@ -137,6 +137,39 @@ test('report test coverage for only changed files', () => { expect(stdout).not.toMatch('b.js'); }); +test('report test coverage of source on test file change under only changed files', () => { + writeFiles(DIR, { + '__tests__/a.test.js': ` + require('../a'); + test('a1', () => expect(1).toBe(1)); + `, + 'a.js': 'module.exports = {}', + 'package.json': JSON.stringify({ + jest: { + collectCoverage: true, + coverageReporters: ['text'], + testEnvironment: 'node', + }, + }), + }); + + run(`${GIT} init`, DIR); + run(`${GIT} add .`, DIR); + run(`${GIT} commit --no-gpg-sign -m "first"`, DIR); + + writeFiles(DIR, { + '__tests__/a.test.js': ` + require('../a'); + test('a1', () => expect(1).toBe(1)); + test('a2', () => expect(2).toBe(2)); + `, + }); + + const {stdout} = runJest(DIR, ['--only-changed']); + + expect(stdout).toMatch('a.js'); +}); + test('do not pickup non-tested files when reporting coverage on only changed files', () => { writeFiles(DIR, { 'a.js': 'module.exports = {}', diff --git a/package.json b/package.json index 3e5841ea2d8c..8658d7699537 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "fast-check": "^1.13.0", "find-process": "^1.4.1", "glob": "^7.1.1", + "globby": "^10.0.2", "graceful-fs": "^4.2.3", "isbinaryfile": "^4.0.0", "istanbul-lib-coverage": "^3.0.0", diff --git a/packages/expect/src/__tests__/__snapshots__/extend.test.js.snap b/packages/expect/src/__tests__/__snapshots__/extend.test.js.snap index b1b67afefea8..68129f9c16d7 100644 --- a/packages/expect/src/__tests__/__snapshots__/extend.test.js.snap +++ b/packages/expect/src/__tests__/__snapshots__/extend.test.js.snap @@ -53,3 +53,15 @@ exports[`is available globally when matcher is unary 1`] = `expected 15 to be di exports[`is available globally when matcher is variadic 1`] = `expected 15 to be within range 1 - 3`; exports[`is ok if there is no message specified 1`] = `No message was specified for this matcher.`; + +exports[`prints the Symbol into the error message 1`] = ` +expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Object { +- "a": toBeSymbol, ++ "a": Symbol(foo), + } +`; diff --git a/packages/expect/src/__tests__/extend.test.js b/packages/expect/src/__tests__/extend.test.js index 7861eafe5852..11b915332fee 100644 --- a/packages/expect/src/__tests__/extend.test.js +++ b/packages/expect/src/__tests__/extend.test.js @@ -23,6 +23,12 @@ jestExpect.extend({ return {message, pass}; }, + toBeSymbol(actual, expected) { + const pass = actual === expected; + const message = () => `expected ${actual} to be Symbol ${expected}`; + + return {message, pass}; + }, toBeWithinRange(actual, floor, ceiling) { const pass = actual >= floor && actual <= ceiling; const message = pass @@ -137,3 +143,14 @@ it('defines asymmetric variadic matchers that can be prefixed by not', () => { }), ).not.toThrow(); }); + +it('prints the Symbol into the error message', () => { + const foo = Symbol('foo'); + const bar = Symbol('bar'); + + expect(() => + jestExpect({a: foo}).toEqual({ + a: jestExpect.toBeSymbol(bar), + }), + ).toThrowErrorMatchingSnapshot(); +}); diff --git a/packages/expect/src/jestMatchersObject.ts b/packages/expect/src/jestMatchersObject.ts index bf08dca6db08..24b2c087071c 100644 --- a/packages/expect/src/jestMatchersObject.ts +++ b/packages/expect/src/jestMatchersObject.ts @@ -78,7 +78,7 @@ export const setMatchers = ( } toAsymmetricMatcher() { - return `${this.toString()}<${this.sample.join(', ')}>`; + return `${this.toString()}<${this.sample.map(String).join(', ')}>`; } } diff --git a/packages/jest-core/src/SearchSource.ts b/packages/jest-core/src/SearchSource.ts index ba70f4ce021d..48c630f2adb4 100644 --- a/packages/jest-core/src/SearchSource.ts +++ b/packages/jest-core/src/SearchSource.ts @@ -51,13 +51,22 @@ const toTests = (context: Context, tests: Array) => path, })); +const hasSCM = (changedFilesInfo: ChangedFiles) => { + const {repos} = changedFilesInfo; + // no SCM (git/hg/...) is found in any of the roots. + const noSCM = Object.values(repos).every(scm => scm.size === 0); + return !noSCM; +}; + export default class SearchSource { private _context: Context; + private _dependencyResolver: DependencyResolver | null; private _testPathCases: TestPathCases = []; constructor(context: Context) { const {config} = context; this._context = context; + this._dependencyResolver = null; const rootPattern = new RegExp( config.roots.map(dir => escapePathForRegex(dir + path.sep)).join('|'), @@ -92,6 +101,17 @@ export default class SearchSource { } } + private _getOrBuildDependencyResolver(): DependencyResolver { + if (!this._dependencyResolver) { + this._dependencyResolver = new DependencyResolver( + this._context.resolver, + this._context.hasteFS, + buildSnapshotResolver(this._context.config), + ); + } + return this._dependencyResolver; + } + private _filterTestPathsWithStats( allPaths: Array, testPathPattern?: string, @@ -155,11 +175,7 @@ export default class SearchSource { allPaths: Set, collectCoverage: boolean, ): SearchResult { - const dependencyResolver = new DependencyResolver( - this._context.resolver, - this._context.hasteFS, - buildSnapshotResolver(this._context.config), - ); + const dependencyResolver = this._getOrBuildDependencyResolver(); if (!collectCoverage) { return { @@ -240,14 +256,11 @@ export default class SearchSource { changedFilesInfo: ChangedFiles, collectCoverage: boolean, ): SearchResult { - const {repos, changedFiles} = changedFilesInfo; - // no SCM (git/hg/...) is found in any of the roots. - const noSCM = (Object.keys(repos) as Array< - keyof ChangedFiles['repos'] - >).every(scm => repos[scm].size === 0); - return noSCM - ? {noSCM: true, tests: []} - : this.findRelatedTests(changedFiles, collectCoverage); + if (!hasSCM(changedFilesInfo)) { + return {noSCM: true, tests: []}; + } + const {changedFiles} = changedFilesInfo; + return this.findRelatedTests(changedFiles, collectCoverage); } private _getTestPaths( @@ -328,4 +341,24 @@ export default class SearchSource { return searchResult; } + + findRelatedSourcesFromTestsInChangedFiles( + changedFilesInfo: ChangedFiles, + ): Array { + if (!hasSCM(changedFilesInfo)) { + return []; + } + const {changedFiles} = changedFilesInfo; + const dependencyResolver = this._getOrBuildDependencyResolver(); + const relatedSourcesSet = new Set(); + changedFiles.forEach(filePath => { + if (this.isTestFilePath(filePath)) { + const sourcePaths = dependencyResolver.resolve(filePath, { + skipNodeResolution: this._context.config.skipNodeResolution, + }); + sourcePaths.forEach(sourcePath => relatedSourcesSet.add(sourcePath)); + } + }); + return Array.from(relatedSourcesSet); + } } diff --git a/packages/jest-core/src/TestScheduler.ts b/packages/jest-core/src/TestScheduler.ts index 41b40e18955f..bf455a2e05c1 100644 --- a/packages/jest-core/src/TestScheduler.ts +++ b/packages/jest-core/src/TestScheduler.ts @@ -44,6 +44,7 @@ export type TestSchedulerContext = { firstRun: boolean; previousSuccess: boolean; changedFiles?: Set; + sourcesRelatedToTestsInChangedFiles?: Set; }; export default class TestScheduler { private _dispatcher: ReporterDispatcher; @@ -180,7 +181,9 @@ export default class TestScheduler { if (!testRunners[config.runner]) { const Runner: typeof TestRunner = require(config.runner); testRunners[config.runner] = new Runner(this._globalConfig, { - changedFiles: this._context && this._context.changedFiles, + changedFiles: this._context?.changedFiles, + sourcesRelatedToTestsInChangedFiles: this._context + ?.sourcesRelatedToTestsInChangedFiles, }); } }); @@ -272,7 +275,9 @@ export default class TestScheduler { if (!isDefault && collectCoverage) { this.addReporter( new CoverageReporter(this._globalConfig, { - changedFiles: this._context && this._context.changedFiles, + changedFiles: this._context?.changedFiles, + sourcesRelatedToTestsInChangedFiles: this._context + ?.sourcesRelatedToTestsInChangedFiles, }), ); } @@ -302,7 +307,9 @@ export default class TestScheduler { if (collectCoverage) { this.addReporter( new CoverageReporter(this._globalConfig, { - changedFiles: this._context && this._context.changedFiles, + changedFiles: this._context?.changedFiles, + sourcesRelatedToTestsInChangedFiles: this._context + ?.sourcesRelatedToTestsInChangedFiles, }), ); } diff --git a/packages/jest-core/src/__tests__/SearchSource.test.ts b/packages/jest-core/src/__tests__/SearchSource.test.ts index 292e5e4b986a..0a6815062c85 100644 --- a/packages/jest-core/src/__tests__/SearchSource.test.ts +++ b/packages/jest-core/src/__tests__/SearchSource.test.ts @@ -531,4 +531,64 @@ describe('SearchSource', () => { } }); }); + + describe('findRelatedSourcesFromTestsInChangedFiles', () => { + const rootDir = path.resolve( + __dirname, + '../../../jest-runtime/src/__tests__/test_root', + ); + + beforeEach(async () => { + const {options: config} = normalize( + { + haste: { + hasteImplModulePath: path.resolve( + __dirname, + '../../../jest-haste-map/src/__tests__/haste_impl.js', + ), + providesModuleNodeModules: [], + }, + name: 'SearchSource-findRelatedSourcesFromTestsInChangedFiles-tests', + rootDir, + }, + {} as Config.Argv, + ); + const context = await Runtime.createContext(config, { + maxWorkers, + watchman: false, + }); + searchSource = new SearchSource(context); + }); + + it('return empty set if no SCM', () => { + const requireRegularModule = path.join( + rootDir, + 'RequireRegularModule.js', + ); + const sources = searchSource.findRelatedSourcesFromTestsInChangedFiles({ + changedFiles: new Set([requireRegularModule]), + repos: { + git: new Set(), + hg: new Set(), + }, + }); + expect(sources).toEqual([]); + }); + + it('return sources required by tests', () => { + const regularModule = path.join(rootDir, 'RegularModule.js'); + const requireRegularModule = path.join( + rootDir, + 'RequireRegularModule.js', + ); + const sources = searchSource.findRelatedSourcesFromTestsInChangedFiles({ + changedFiles: new Set([requireRegularModule]), + repos: { + git: new Set('/path/to/git'), + hg: new Set(), + }, + }); + expect(sources).toEqual([regularModule]); + }); + }); }); diff --git a/packages/jest-core/src/runJest.ts b/packages/jest-core/src/runJest.ts index 38bcb8dc95be..bea930899c0d 100644 --- a/packages/jest-core/src/runJest.ts +++ b/packages/jest-core/src/runJest.ts @@ -34,13 +34,12 @@ import type {Filter, TestRunData} from './types'; const getTestPaths = async ( globalConfig: Config.GlobalConfig, - context: Context, + source: SearchSource, outputStream: NodeJS.WriteStream, changedFiles: ChangedFiles | undefined, jestHooks: JestHookEmitter, filter?: Filter, ) => { - const source = new SearchSource(context); const data = await source.getTestPaths(globalConfig, changedFiles, filter); if (!data.tests.length && globalConfig.onlyChanged && data.noSCM) { @@ -167,11 +166,14 @@ export default async function runJest({ } } + const searchSources = contexts.map(context => new SearchSource(context)); + const testRunData: TestRunData = await Promise.all( - contexts.map(async context => { + contexts.map(async (context, index) => { + const searchSource = searchSources[index]; const matches = await getTestPaths( globalConfig, - context, + searchSource, outputStream, changedFilesPromise && (await changedFilesPromise), jestHooks, @@ -242,9 +244,22 @@ export default async function runJest({ } if (changedFilesPromise) { - testSchedulerContext.changedFiles = ( - await changedFilesPromise - ).changedFiles; + const changedFilesInfo = await changedFilesPromise; + if (changedFilesInfo.changedFiles) { + testSchedulerContext.changedFiles = changedFilesInfo.changedFiles; + const sourcesRelatedToTestsInChangedFilesArray = contexts + .map((_, index) => { + const searchSource = searchSources[index]; + const relatedSourceFromTestsInChangedFiles = searchSource.findRelatedSourcesFromTestsInChangedFiles( + changedFilesInfo, + ); + return relatedSourceFromTestsInChangedFiles; + }) + .reduce((total, paths) => total.concat(paths), []); + testSchedulerContext.sourcesRelatedToTestsInChangedFiles = new Set( + sourcesRelatedToTestsInChangedFilesArray, + ); + } } const results = await new TestScheduler( diff --git a/packages/jest-environment/tsconfig.json b/packages/jest-environment/tsconfig.json index 658545960324..efa01e2b2db4 100644 --- a/packages/jest-environment/tsconfig.json +++ b/packages/jest-environment/tsconfig.json @@ -1,6 +1,8 @@ { "extends": "../../tsconfig.json", "compilerOptions": { + // we don't want `@types/jest` to be referenced + "types": ["node"], "rootDir": "src", "outDir": "build" }, diff --git a/packages/jest-reporters/src/__tests__/coverage_worker.test.js b/packages/jest-reporters/src/__tests__/coverage_worker.test.js index b3351ba29006..86cfeecb1ab3 100644 --- a/packages/jest-reporters/src/__tests__/coverage_worker.test.js +++ b/packages/jest-reporters/src/__tests__/coverage_worker.test.js @@ -41,6 +41,7 @@ test('resolves to the result of generateEmptyCoverage upon success', async () => globalConfig, config, undefined, + undefined, ); expect(result).toEqual(42); diff --git a/packages/jest-reporters/src/coverage_reporter.ts b/packages/jest-reporters/src/coverage_reporter.ts index 4ec8d75961ac..1e87c21bdbd8 100644 --- a/packages/jest-reporters/src/coverage_reporter.ts +++ b/packages/jest-reporters/src/coverage_reporter.ts @@ -182,6 +182,9 @@ export default class CoverageReporter extends BaseReporter { changedFiles: this._options.changedFiles && Array.from(this._options.changedFiles), + sourcesRelatedToTestsInChangedFiles: + this._options.sourcesRelatedToTestsInChangedFiles && + Array.from(this._options.sourcesRelatedToTestsInChangedFiles), }, path: filename, }); diff --git a/packages/jest-reporters/src/coverage_worker.ts b/packages/jest-reporters/src/coverage_worker.ts index 23109ffa16ee..d1894b97574c 100644 --- a/packages/jest-reporters/src/coverage_worker.ts +++ b/packages/jest-reporters/src/coverage_worker.ts @@ -40,6 +40,8 @@ export function worker({ path, globalConfig, config, - options && options.changedFiles && new Set(options.changedFiles), + options?.changedFiles && new Set(options.changedFiles), + options?.sourcesRelatedToTestsInChangedFiles && + new Set(options.sourcesRelatedToTestsInChangedFiles), ); } diff --git a/packages/jest-reporters/src/generateEmptyCoverage.ts b/packages/jest-reporters/src/generateEmptyCoverage.ts index b6c270060fdd..38f184d61558 100644 --- a/packages/jest-reporters/src/generateEmptyCoverage.ts +++ b/packages/jest-reporters/src/generateEmptyCoverage.ts @@ -30,6 +30,7 @@ export default function ( globalConfig: Config.GlobalConfig, config: Config.ProjectConfig, changedFiles?: Set, + sourcesRelatedToTestsInChangedFiles?: Set, ): CoverageWorkerResult | null { const coverageOptions = { changedFiles, @@ -37,6 +38,7 @@ export default function ( collectCoverageFrom: globalConfig.collectCoverageFrom, collectCoverageOnlyFrom: globalConfig.collectCoverageOnlyFrom, coverageProvider: globalConfig.coverageProvider, + sourcesRelatedToTestsInChangedFiles, }; let coverageWorkerResult: CoverageWorkerResult | null = null; if (shouldInstrument(filename, coverageOptions, config)) { diff --git a/packages/jest-reporters/src/types.ts b/packages/jest-reporters/src/types.ts index ddfde5782362..d2725ead5917 100644 --- a/packages/jest-reporters/src/types.ts +++ b/packages/jest-reporters/src/types.ts @@ -37,10 +37,12 @@ export type CoverageWorker = {worker: typeof worker}; export type CoverageReporterOptions = { changedFiles?: Set; + sourcesRelatedToTestsInChangedFiles?: Set; }; export type CoverageReporterSerializedOptions = { changedFiles?: Array; + sourcesRelatedToTestsInChangedFiles?: Array; }; export type OnTestStart = (test: Test) => Promise; diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index fb3e93ea0eda..dd8735be8b57 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -147,11 +147,13 @@ async function runTestInternal( setGlobal(environment.global, 'console', testConsole); const runtime = new Runtime(config, environment, resolver, cacheFS, { - changedFiles: context && context.changedFiles, + changedFiles: context?.changedFiles, collectCoverage: globalConfig.collectCoverage, collectCoverageFrom: globalConfig.collectCoverageFrom, collectCoverageOnlyFrom: globalConfig.collectCoverageOnlyFrom, coverageProvider: globalConfig.coverageProvider, + sourcesRelatedToTestsInChangedFiles: + context?.sourcesRelatedToTestsInChangedFiles, }); const start = Date.now(); diff --git a/packages/jest-runner/src/types.ts b/packages/jest-runner/src/types.ts index c45b44d32677..4862c886ce86 100644 --- a/packages/jest-runner/src/types.ts +++ b/packages/jest-runner/src/types.ts @@ -51,6 +51,7 @@ export type TestRunnerOptions = { export type TestRunnerContext = { changedFiles?: Set; + sourcesRelatedToTestsInChangedFiles?: Set; }; export type TestRunnerSerializedContext = { diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 363c18ba846f..ecb2d25f3ef8 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -171,6 +171,7 @@ class Runtime { collectCoverageFrom: [], collectCoverageOnlyFrom: undefined, coverageProvider: 'babel', + sourcesRelatedToTestsInChangedFiles: undefined, }; this._currentlyExecutingModulePath = ''; this._environment = environment; diff --git a/packages/jest-transform/src/shouldInstrument.ts b/packages/jest-transform/src/shouldInstrument.ts index e9d75afdbc63..d9fcdcd268c3 100644 --- a/packages/jest-transform/src/shouldInstrument.ts +++ b/packages/jest-transform/src/shouldInstrument.ts @@ -94,7 +94,12 @@ export default function shouldInstrument( } if (options.changedFiles && !options.changedFiles.has(filename)) { - return false; + if (!options.sourcesRelatedToTestsInChangedFiles) { + return false; + } + if (!options.sourcesRelatedToTestsInChangedFiles.has(filename)) { + return false; + } } return true; diff --git a/packages/jest-transform/src/types.ts b/packages/jest-transform/src/types.ts index 138bab7f5406..b984980e1112 100644 --- a/packages/jest-transform/src/types.ts +++ b/packages/jest-transform/src/types.ts @@ -16,6 +16,7 @@ export type ShouldInstrumentOptions = Pick< | 'coverageProvider' > & { changedFiles?: Set; + sourcesRelatedToTestsInChangedFiles?: Set; }; export type Options = ShouldInstrumentOptions & diff --git a/scripts/buildTs.js b/scripts/buildTs.js index af57239ed718..9f8ed9c3c7cb 100644 --- a/scripts/buildTs.js +++ b/scripts/buildTs.js @@ -11,13 +11,17 @@ const assert = require('assert'); const fs = require('fs'); const os = require('os'); const path = require('path'); +const util = require('util'); const chalk = require('chalk'); const execa = require('execa'); +const globby = require('globby'); const rimraf = require('rimraf'); const throat = require('throat'); const {getPackages} = require('./buildUtils'); +const readFilePromise = util.promisify(fs.readFile); + const packages = getPackages(); const packagesWithTs = packages.filter(p => @@ -64,23 +68,66 @@ try { return; } -const downlevelArgs = ['--silent', 'downlevel-dts', 'build', 'build/ts3.4']; - -console.log(chalk.inverse(' Downleveling TypeScript definition files ')); - // we want to limit the number of processes we spawn const cpus = Math.max(1, os.cpus().length - 1); Promise.all( packagesWithTs.map( - throat(cpus, pkgDir => { - // otherwise we get nested `ts3.4` directories - rimraf.sync(path.resolve(pkgDir, 'build/ts3.4')); - - return execa('yarn', downlevelArgs, {cwd: pkgDir, stdio: 'inherit'}); + throat(cpus, async pkgDir => { + const buildDir = path.resolve(pkgDir, 'build/**/*.d.ts'); + const ts3dot4 = path.resolve(pkgDir, 'build/ts3.4'); + + const globbed = await globby([buildDir, `!${ts3dot4}`]); + + const files = await Promise.all( + globbed.map(file => Promise.all([file, readFilePromise(file, 'utf8')])), + ); + + const filesWithReferences = files + .filter(([, content]) => content.includes('/// [ + name, + content + .split('\n') + .filter(line => line !== '/// ') + .filter(line => line.includes('/// content.length > 0) + .filter(hit => hit.length > 0) + .map(([file, references]) => + chalk.red( + `${chalk.bold( + file, + )} has the following non-node type references:\n\n${references}\n`, + ), + ) + .join('\n\n'); + + if (filesWithReferences) { + console.error(filesWithReferences); + + process.exit(1); + } }), ), ) + .then(() => { + const downlevelArgs = ['--silent', 'downlevel-dts', 'build', 'build/ts3.4']; + + console.log(chalk.inverse(' Downleveling TypeScript definition files ')); + + return Promise.all( + packagesWithTs.map( + throat(cpus, pkgDir => { + // otherwise we get nested `ts3.4` directories + rimraf.sync(path.resolve(pkgDir, 'build/ts3.4')); + + return execa('yarn', downlevelArgs, {cwd: pkgDir, stdio: 'inherit'}); + }), + ), + ); + }) .then(() => { console.log( chalk.inverse.green( diff --git a/yarn.lock b/yarn.lock index e3aa5642fd7c..9ca11d8bef55 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1899,11 +1899,32 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + "@nodelib/fs.stat@^1.1.2": version "1.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + "@octokit/auth-token@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.0.tgz#b64178975218b99e4dfe948253f0673cbbb59d9f" @@ -3228,6 +3249,11 @@ array-union@^1.0.1, array-union@^1.0.2: dependencies: array-uniq "^1.0.1" +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" @@ -5484,6 +5510,13 @@ dir-glob@^2.2.2: dependencies: path-type "^3.0.0" +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + discontinuous-range@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" @@ -6576,6 +6609,18 @@ fast-glob@^2.0.2, fast-glob@^2.2.6: merge2 "^1.2.3" micromatch "^3.1.10" +fast-glob@^3.0.3: + version "3.2.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" + integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -6586,6 +6631,13 @@ fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fastq@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.7.0.tgz#fcd79a08c5bd7ec5b55cd3f5c4720db551929801" + integrity sha512-YOadQRnHd5q6PogvAR/x62BGituF2ufiEA6s8aavQANw5YKHERI4AREboX6KotzP8oX2klxYF2wcV/7bn1clfQ== + dependencies: + reusify "^1.0.4" + faye-websocket@~0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" @@ -7263,7 +7315,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0, glob-parent@~5.1.0: +glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== @@ -7340,6 +7392,20 @@ globby@8.0.2, globby@^8.0.1: pify "^3.0.0" slash "^1.0.0" +globby@^10.0.2: + version "10.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" + integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + globby@^9.2.0: version "9.2.0" resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" @@ -7819,7 +7885,7 @@ ignore@^4.0.3, ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.0.5: +ignore@^5.0.5, ignore@^5.1.1: version "5.1.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== @@ -9772,7 +9838,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.2.3: +merge2@^1.2.3, merge2@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== @@ -11314,6 +11380,11 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" @@ -11335,7 +11406,7 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7: +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== @@ -12705,6 +12776,11 @@ retry@^0.10.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q= +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + rfdc@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2" @@ -12774,6 +12850,11 @@ run-async@^2.2.0, run-async@^2.4.0: dependencies: is-promise "^2.1.0" +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"