diff --git a/package.json b/package.json index e5f87ba2ab0..8ca8670fcb9 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "release": "lerna publish -y from-package --dist-tag=next --no-git-tag-version --no-push" }, "devDependencies": { - "@babel/core": "^7.8.7", + "@babel/core": "^7.12.0", "cross-env": "^7.0.0", "doctoc": "^1.4.0", "eslint": "^6.0.0", diff --git a/packages/core/core/src/ParcelConfig.schema.js b/packages/core/core/src/ParcelConfig.schema.js index eb224f19690..e0076de6a27 100644 --- a/packages/core/core/src/ParcelConfig.schema.js +++ b/packages/core/core/src/ParcelConfig.schema.js @@ -110,9 +110,7 @@ export default { }, bundler: { type: 'string', - __validate: (validatePluginName('bundler', 'bundler'): ( - val: string, - ) => void), + __validate: (validatePluginName('bundler', 'bundler'): string => void), }, resolvers: (pipelineSchema('resolver', 'resolvers'): SchemaEntity), transformers: (mapPipelineSchema( diff --git a/packages/core/core/src/worker.js b/packages/core/core/src/worker.js index fd2396fdaa7..f645fe9ca0f 100644 --- a/packages/core/core/src/worker.js +++ b/packages/core/core/src/worker.js @@ -150,3 +150,24 @@ export async function runPackage( runner.getBundleInfo(bundle, bundleGraph, cacheKeys, configs) ); } + +const PKG_RE = /node_modules[/\\]((?:@[^/\\]+\/[^/\\]+)|[^/\\]+)(?!.*[/\\]node_modules[/\\])/; +export function invalidateRequireCache(workerApi: WorkerApi, file: string) { + if (process.env.PARCEL_BUILD_ENV === 'test') { + // Delete this module and all children in the same node_modules folder + let module = require.cache[file]; + if (module) { + delete require.cache[file]; + + let pkg = file.match(PKG_RE)?.[1]; + for (let child of module.children) { + if (pkg === child.id.match(PKG_RE)?.[1]) { + invalidateRequireCache(workerApi, child.id); + } + } + } + return; + } + + throw new Error('invalidateRequireCache is only for tests'); +} diff --git a/packages/core/integration-tests/package.json b/packages/core/integration-tests/package.json index 82999fb8390..d9a7e50f54d 100644 --- a/packages/core/integration-tests/package.json +++ b/packages/core/integration-tests/package.json @@ -12,7 +12,7 @@ "test-ci": "yarn test --reporter mocha-multi-reporters --reporter-options configFile=./test/mochareporters.json" }, "devDependencies": { - "@babel/core": "^7.4.4", + "@babel/core": "^7.12.0", "@babel/plugin-syntax-export-default-from": "^7.2.0", "@babel/plugin-syntax-export-namespace-from": "^7.2.0", "@babel/plugin-syntax-module-attributes": "^7.10.4", diff --git a/packages/core/integration-tests/test/cache.js b/packages/core/integration-tests/test/cache.js index 35dd41b8cc5..4e1de620e17 100644 --- a/packages/core/integration-tests/test/cache.js +++ b/packages/core/integration-tests/test/cache.js @@ -9,17 +9,21 @@ import { overlayFS, inputFS, ncp, + workerFarm, } from '@parcel/test-utils'; +import fs from 'fs'; + +let inputDir: string; function runBundle(entries = 'src/index.js', opts) { entries = (Array.isArray(entries) ? entries : [entries]).map(entry => - path.join(__dirname, 'input', entry), + path.join(inputDir, entry), ); return bundler(entries, { - ...opts, inputFS: overlayFS, disableCache: false, + ...opts, }).run(); } @@ -34,15 +38,11 @@ type TestConfig = {| |}; async function testCache(update: UpdateFn | TestConfig, integration) { - // Delete cache from previous test and perform initial build - await inputFS.rimraf(path.join(__dirname, '/input')); await overlayFS.rimraf(path.join(__dirname, '/input')); await ncp( path.join(__dirname, '/integration', integration ?? 'cache'), - path.join(__dirname, '/input'), + path.join(inputDir), ); - await overlayFS.rimraf(path.join(__dirname, '/input/.parcel-cache')); - await overlayFS.rimraf(path.join(__dirname, '/input/dist')); let entries; let options: ?InitialParcelOptions; @@ -67,11 +67,25 @@ async function testCache(update: UpdateFn | TestConfig, integration) { } describe('cache', function() { + before(async () => { + await inputFS.rimraf(path.join(__dirname, 'input')); + }); + + beforeEach(() => { + inputDir = path.join( + __dirname, + '/input', + Math.random() + .toString(36) + .slice(2), + ); + }); + it('should support updating a JS file', async function() { let b = await testCache(async b => { assert.equal(await run(b.bundleGraph), 4); await overlayFS.writeFile( - path.join(__dirname, '/input/src/nested/test.js'), + path.join(inputDir, 'src/nested/test.js'), 'export default 4', ); }); @@ -83,11 +97,11 @@ describe('cache', function() { let b = await testCache(async b => { assert.equal(await run(b.bundleGraph), 4); await overlayFS.writeFile( - path.join(__dirname, '/input/src/nested/foo.js'), + path.join(inputDir, 'src/nested/foo.js'), 'export default 6', ); await overlayFS.writeFile( - path.join(__dirname, '/input/src/nested/test.js'), + path.join(inputDir, 'src/nested/test.js'), 'export {default} from "./foo";', ); }); @@ -100,9 +114,7 @@ describe('cache', function() { await assert.rejects( async () => { await testCache(async () => { - await overlayFS.unlink( - path.join(__dirname, '/input/src/nested/test.js'), - ); + await overlayFS.unlink(path.join(inputDir, 'src/nested/test.js')); }); }, {message: "Failed to resolve './nested/test' from './src/index.js'"}, @@ -113,9 +125,7 @@ describe('cache', function() { // $FlowFixMe await assert.rejects(async () => { await testCache(async () => { - await overlayFS.unlink( - path.join(__dirname, '/input/src/nested/test.js'), - ); + await overlayFS.unlink(path.join(inputDir, 'src/nested/test.js')); }); }); @@ -130,19 +140,811 @@ describe('cache', function() { }); describe('babel', function() { - it('should support adding a .babelrc', function() {}); + let json = config => JSON.stringify(config); + let cjs = config => `module.exports = ${JSON.stringify(config)}`; + // TODO: not sure how to invalidate the ESM cache in node... + // let mjs = (config) => `export default ${JSON.stringify(config)}`; + let configs = [ + {name: '.babelrc', formatter: json, nesting: true}, + {name: '.babelrc.json', formatter: json, nesting: true}, + {name: '.babelrc.js', formatter: cjs, nesting: true}, + {name: '.babelrc.cjs', formatter: cjs, nesting: true}, + // {name: '.babelrc.mjs', formatter: mjs, nesting: true}, + {name: 'babel.config.json', formatter: json, nesting: false}, + {name: 'babel.config.js', formatter: cjs, nesting: false}, + {name: 'babel.config.cjs', formatter: cjs, nesting: false}, + // {name: 'babel.config.mjs', formatter: mjs, nesting: false} + ]; + + let testBabelCache = async (opts: TestConfig) => { + await workerFarm.callAllWorkers('invalidateRequireCache', [ + require.resolve('@babel/core'), + ]); + + return testCache({ + ...opts, + async update(...args) { + await opts.update(...args); + + // invalidate babel's caches since we're simulating a process restart + await workerFarm.callAllWorkers('invalidateRequireCache', [ + require.resolve('@babel/core'), + ]); + }, + }); + }; + + for (let {name, formatter, nesting} of configs) { + describe(name, function() { + beforeEach(async () => { + await workerFarm.callAllWorkers('invalidateRequireCache', [ + path.join(inputDir, name), + ]); + }); + + it(`should support adding a ${name}`, async function() { + let b = await testBabelCache({ + // Babel's config loader only works with the node filesystem + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/cache'), + inputDir, + ); + }, + async update(b) { + assert.equal(await run(b.bundleGraph), 4); + + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + contents.includes('class Test'), + 'class should not be transpiled', + ); + + await inputFS.writeFile( + path.join(inputDir, name), + formatter({ + presets: ['@babel/preset-env'], + }), + ); + }, + }); + + assert.equal(await run(b.bundleGraph), 4); + + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + !contents.includes('class Test'), + 'class should be transpiled', + ); + }); - it('should support updating a .babelrc', function() {}); + it(`should support updating a ${name}`, async function() { + let b = await testBabelCache({ + // Babel's config loader only works with the node filesystem + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/cache'), + inputDir, + ); + await inputFS.writeFile( + path.join(inputDir, name), + formatter({ + presets: [ + ['@babel/preset-env', {targets: {esmodules: true}}], + ], + }), + ); + }, + async update(b) { + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + contents.includes('class Test'), + 'class should not be transpiled', + ); - it('should support updating an extended .babelrc', function() {}); + await inputFS.writeFile( + path.join(inputDir, name), + formatter({ + presets: ['@babel/preset-env'], + }), + ); - it('should support adding a nested .babelrc', function() {}); + await workerFarm.callAllWorkers('invalidateRequireCache', [ + path.join(inputDir, name), + ]); + }, + }); - it('should support updating a nested .babelrc', function() {}); + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + !contents.includes('class Test'), + 'class should be transpiled', + ); + }); - it('should support deleting a nested .babelrc', function() {}); + it(`should support deleting a ${name}`, async function() { + let b = await testBabelCache({ + // Babel's config loader only works with the node filesystem + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/cache'), + inputDir, + ); + await inputFS.writeFile( + path.join(inputDir, name), + formatter({ + presets: ['@babel/preset-env'], + }), + ); + }, + async update(b) { + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + !contents.includes('class Test'), + 'class should be transpiled', + ); - it('should support deleting a custom .babelrc', function() {}); + await inputFS.unlink(path.join(inputDir, name)); + }, + }); + + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + contents.includes('class Test'), + 'class should not be transpiled', + ); + }); + + it(`should support updating an extended ${name}`, async function() { + let extendedName = '.babelrc-extended' + path.extname(name); + let b = await testBabelCache({ + // Babel's config loader only works with the node filesystem + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/cache'), + inputDir, + ); + await inputFS.writeFile( + path.join(inputDir, extendedName), + formatter({ + presets: [ + ['@babel/preset-env', {targets: {esmodules: true}}], + ], + }), + ); + await inputFS.writeFile( + path.join(inputDir, name), + formatter({ + extends: `./${extendedName}`, + }), + ); + await workerFarm.callAllWorkers('invalidateRequireCache', [ + path.join(inputDir, extendedName), + ]); + }, + async update(b) { + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + contents.includes('class Test'), + 'class should not be transpiled', + ); + + await inputFS.writeFile( + path.join(inputDir, extendedName), + formatter({ + presets: ['@babel/preset-env'], + }), + ); + + await workerFarm.callAllWorkers('invalidateRequireCache', [ + path.join(inputDir, extendedName), + ]); + }, + }); + + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + !contents.includes('class Test'), + 'class should be transpiled', + ); + }); + + if (nesting) { + it(`should support adding a nested ${name}`, async function() { + let b = await testBabelCache({ + // Babel's config loader only works with the node filesystem + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/cache'), + inputDir, + ); + }, + async update(b) { + assert.equal(await run(b.bundleGraph), 4); + + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + contents.includes('class Test'), + 'class should not be transpiled', + ); + assert( + contents.includes('class Result'), + 'class should not be transpiled', + ); + + await inputFS.writeFile( + path.join(inputDir, `src/nested/${name}`), + formatter({ + presets: ['@babel/preset-env'], + }), + ); + }, + }); + + assert.equal(await run(b.bundleGraph), 4); + + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + !contents.includes('class Test'), + 'class should be transpiled', + ); + assert( + contents.includes('class Result'), + 'class should not be transpiled', + ); + }); + + it(`should support updating a nested ${name}`, async function() { + let b = await testBabelCache({ + // Babel's config loader only works with the node filesystem + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/cache'), + inputDir, + ); + await inputFS.writeFile( + path.join(inputDir, `src/nested/${name}`), + formatter({ + presets: [ + ['@babel/preset-env', {targets: {esmodules: true}}], + ], + }), + ); + await workerFarm.callAllWorkers('invalidateRequireCache', [ + path.join(inputDir, `src/nested/${name}`), + ]); + }, + async update(b) { + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + contents.includes('class Test'), + 'class should not be transpiled', + ); + assert( + contents.includes('class Result'), + 'class should not be transpiled', + ); + + await inputFS.writeFile( + path.join(inputDir, `src/nested/${name}`), + formatter({ + presets: ['@babel/preset-env'], + }), + ); + + await workerFarm.callAllWorkers('invalidateRequireCache', [ + path.join(inputDir, `src/nested/${name}`), + ]); + }, + }); + + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + !contents.includes('class Test'), + 'class should be transpiled', + ); + assert( + contents.includes('class Result'), + 'class should not be transpiled', + ); + }); + + it(`should support deleting a nested ${name}`, async function() { + let b = await testBabelCache({ + // Babel's config loader only works with the node filesystem + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/cache'), + inputDir, + ); + await inputFS.writeFile( + path.join(inputDir, `src/nested/${name}`), + formatter({ + presets: ['@babel/preset-env'], + }), + ); + }, + async update(b) { + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + !contents.includes('class Test'), + 'class should be transpiled', + ); + assert( + contents.includes('class Result'), + 'class should not be transpiled', + ); + + await inputFS.unlink(path.join(inputDir, `src/nested/${name}`)); + }, + }); + + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + contents.includes('class Test'), + 'class should not be transpiled', + ); + assert( + contents.includes('class Result'), + 'class should not be transpiled', + ); + }); + } + }); + } + + describe('.babelignore', function() { + it('should support adding a .babelignore', async function() { + let b = await testBabelCache({ + // Babel's config loader only works with the node filesystem + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/cache'), + inputDir, + ); + await inputFS.writeFile( + path.join(inputDir, '.babelrc'), + JSON.stringify({ + presets: ['@babel/preset-env'], + }), + ); + }, + async update(b) { + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + !contents.includes('class Test'), + 'class should be transpiled', + ); + assert( + !contents.includes('class Result'), + 'class should be transpiled', + ); + + await inputFS.writeFile( + path.join(inputDir, '.babelignore'), + 'src/nested', + ); + }, + }); + + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + contents.includes('class Test'), + 'class should not be transpiled', + ); + assert( + !contents.includes('class Result'), + 'class should be transpiled', + ); + }); + + it('should support updating a .babelignore', async function() { + let b = await testBabelCache({ + // Babel's config loader only works with the node filesystem + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/cache'), + inputDir, + ); + await inputFS.writeFile( + path.join(inputDir, '.babelrc'), + JSON.stringify({ + presets: ['@babel/preset-env'], + }), + ); + await inputFS.writeFile( + path.join(inputDir, '.babelignore'), + 'src/nested', + ); + }, + async update(b) { + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + contents.includes('class Test'), + 'class should not be transpiled', + ); + assert( + !contents.includes('class Result'), + 'class should be transpiled', + ); + + await inputFS.writeFile(path.join(inputDir, '.babelignore'), 'src'); + }, + }); + + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + contents.includes('class Test'), + 'class should not be transpiled', + ); + assert( + contents.includes('class Result'), + 'class should not be transpiled', + ); + }); + + it('should support deleting a .babelignore', async function() { + let b = await testBabelCache({ + // Babel's config loader only works with the node filesystem + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/cache'), + inputDir, + ); + await inputFS.writeFile( + path.join(inputDir, '.babelrc'), + JSON.stringify({ + presets: ['@babel/preset-env'], + }), + ); + await inputFS.writeFile( + path.join(inputDir, '.babelignore'), + 'src/nested', + ); + }, + async update(b) { + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + contents.includes('class Test'), + 'class should not be transpiled', + ); + assert( + !contents.includes('class Result'), + 'class should be transpiled', + ); + + await inputFS.unlink(path.join(inputDir, '.babelignore')); + }, + }); + + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(!contents.includes('class Test'), 'class should be transpiled'); + assert( + !contents.includes('class Result'), + 'class should be transpiled', + ); + }); + }); + + describe('plugins', function() { + it('should invalidate when plugins change versions', async function() { + let b = await testBabelCache({ + // Babel's config loader only works with the node filesystem + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/cache'), + inputDir, + ); + await inputFS.mkdirp( + path.join(inputDir, 'node_modules/babel-plugin-dummy'), + ); + await inputFS.writeFile( + path.join( + inputDir, + '/node_modules/babel-plugin-dummy/package.json', + ), + JSON.stringify({ + name: 'babel-plugin-dummy', + version: '1.0.0', + }), + ); + await inputFS.copyFile( + path.join( + __dirname, + '/integration/babelrc-custom/babel-plugin-dummy.js', + ), + path.join(inputDir, '/node_modules/babel-plugin-dummy/index.js'), + ); + await inputFS.writeFile( + path.join(inputDir, '.babelrc'), + JSON.stringify({ + plugins: ['babel-plugin-dummy'], + }), + ); + await inputFS.writeFile( + path.join(inputDir, 'src/index.js'), + 'console.log("REPLACE_ME")', + ); + }, + async update(b) { + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + contents.includes('hello there'), + 'string should be replaced', + ); + + let plugin = path.join( + inputDir, + 'node_modules/babel-plugin-dummy/index.js', + ); + let source = await inputFS.readFile(plugin, 'utf8'); + await inputFS.writeFile( + plugin, + source.replace('hello there', 'replaced'), + ); + + await inputFS.writeFile( + path.join( + inputDir, + 'node_modules/babel-plugin-dummy/package.json', + ), + JSON.stringify({ + name: 'babel-plugin-dummy', + version: '2.0.0', + }), + ); + + await workerFarm.callAllWorkers('invalidateRequireCache', [ + path.join(inputDir, 'node_modules/babel-plugin-dummy/index.js'), + ]); + }, + }); + + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(contents.includes('replaced'), 'string should be replaced'); + }); + + it('should invalidate on startup when there are relative plugins', async function() { + let b = await testBabelCache({ + // Babel's config loader only works with the node filesystem + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/cache'), + inputDir, + ); + await inputFS.copyFile( + path.join( + __dirname, + '/integration/babelrc-custom/babel-plugin-dummy.js', + ), + path.join(inputDir, 'babel-plugin-dummy.js'), + ); + await inputFS.writeFile( + path.join(inputDir, '.babelrc'), + JSON.stringify({ + plugins: ['./babel-plugin-dummy'], + }), + ); + await inputFS.writeFile( + path.join(inputDir, 'src/index.js'), + 'console.log("REPLACE_ME")', + ); + }, + async update(b) { + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + contents.includes('hello there'), + 'string should be replaced', + ); + + let plugin = path.join(inputDir, 'babel-plugin-dummy.js'); + let source = await inputFS.readFile(plugin, 'utf8'); + await inputFS.writeFile( + plugin, + source.replace('hello there', 'replaced'), + ); + + await workerFarm.callAllWorkers('invalidateRequireCache', [ + path.join(inputDir, 'babel-plugin-dummy.js'), + ]); + }, + }); + + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(contents.includes('replaced'), 'string should be replaced'); + }); + + it('should invalidate on startup when there are symlinked plugins', async function() { + // Symlinks don't work consistently on windows. Skip this test. + if (process.platform === 'win32') { + this.skip(); + return; + } + + let b = await testBabelCache({ + // Babel's config loader only works with the node filesystem + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/cache'), + inputDir, + ); + await inputFS.mkdirp( + path.join(inputDir, 'packages/babel-plugin-dummy'), + ); + await inputFS.mkdirp(path.join(inputDir, 'node_modules')); + fs.symlinkSync( + path.join(inputDir, 'packages/babel-plugin-dummy'), + path.join(inputDir, 'node_modules/babel-plugin-dummy'), + ); + await inputFS.writeFile( + path.join(inputDir, 'packages/babel-plugin-dummy/package.json'), + JSON.stringify({ + name: 'babel-plugin-dummy', + version: '1.0.0', + }), + ); + await inputFS.copyFile( + path.join( + __dirname, + '/integration/babelrc-custom/babel-plugin-dummy.js', + ), + path.join(inputDir, 'packages/babel-plugin-dummy/index.js'), + ); + await inputFS.writeFile( + path.join(inputDir, '.babelrc'), + JSON.stringify({ + plugins: ['babel-plugin-dummy'], + }), + ); + await inputFS.writeFile( + path.join(inputDir, 'src/index.js'), + 'console.log("REPLACE_ME")', + ); + }, + async update(b) { + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert( + contents.includes('hello there'), + 'string should be replaced', + ); + + let plugin = path.join( + inputDir, + 'packages/babel-plugin-dummy/index.js', + ); + let source = await inputFS.readFile(plugin, 'utf8'); + await inputFS.writeFile( + plugin, + source.replace('hello there', 'replaced'), + ); + + await workerFarm.callAllWorkers('invalidateRequireCache', [ + path.join(inputDir, 'packages/babel-plugin-dummy/index.js'), + ]); + }, + }); + + let contents = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(contents.includes('replaced'), 'string should be replaced'); + }); + }); }); describe('parcel config', function() { @@ -157,7 +959,7 @@ describe('cache', function() { assert(!contents.includes('TRANSFORMED CODE')); await overlayFS.writeFile( - path.join(__dirname, '/input/.parcelrc'), + path.join(inputDir, '.parcelrc'), JSON.stringify({ extends: '@parcel/config-default', transformers: { @@ -178,7 +980,7 @@ describe('cache', function() { let b = await testCache({ async setup() { await overlayFS.writeFile( - path.join(__dirname, '/input/.parcelrc'), + path.join(inputDir, '.parcelrc'), JSON.stringify({ extends: '@parcel/config-default', transformers: { @@ -195,7 +997,7 @@ describe('cache', function() { assert(contents.includes('TRANSFORMED CODE')); await overlayFS.writeFile( - path.join(__dirname, '/input/.parcelrc'), + path.join(inputDir, '.parcelrc'), JSON.stringify({ extends: '@parcel/config-default', }), @@ -216,7 +1018,7 @@ describe('cache', function() { let b = await testCache({ async setup() { await overlayFS.writeFile( - path.join(__dirname, '/input/.parcelrc-extended'), + path.join(inputDir, '.parcelrc-extended'), JSON.stringify({ extends: '@parcel/config-default', transformers: { @@ -226,7 +1028,7 @@ describe('cache', function() { ); await overlayFS.writeFile( - path.join(__dirname, '/input/.parcelrc'), + path.join(inputDir, '.parcelrc'), JSON.stringify({ extends: './.parcelrc-extended', }), @@ -240,7 +1042,7 @@ describe('cache', function() { assert(contents.includes('TRANSFORMED CODE')); await overlayFS.writeFile( - path.join(__dirname, '/input/.parcelrc-extended'), + path.join(inputDir, '.parcelrc-extended'), JSON.stringify({ extends: '@parcel/config-default', }), @@ -264,7 +1066,7 @@ describe('cache', function() { await testCache({ async setup() { await overlayFS.writeFile( - path.join(__dirname, '/input/.parcelrc-extended'), + path.join(inputDir, '.parcelrc-extended'), JSON.stringify({ extends: '@parcel/config-default', transformers: { @@ -274,7 +1076,7 @@ describe('cache', function() { ); await overlayFS.writeFile( - path.join(__dirname, '/input/.parcelrc'), + path.join(inputDir, '.parcelrc'), JSON.stringify({ extends: './.parcelrc-extended', }), @@ -287,9 +1089,7 @@ describe('cache', function() { ); assert(contents.includes('TRANSFORMED CODE')); - await overlayFS.unlink( - path.join(__dirname, '/input/.parcelrc-extended'), - ); + await overlayFS.unlink(path.join(inputDir, '.parcelrc-extended')); }, }); }, @@ -301,7 +1101,7 @@ describe('cache', function() { let b = await testCache({ async setup() { await overlayFS.writeFile( - path.join(__dirname, '/input/.parcelrc'), + path.join(inputDir, '.parcelrc'), JSON.stringify({ extends: '@parcel/config-default', transformers: { @@ -317,7 +1117,7 @@ describe('cache', function() { ); assert(contents.includes('TRANSFORMED CODE')); - await overlayFS.unlink(path.join(__dirname, '/input/.parcelrc')); + await overlayFS.unlink(path.join(inputDir, '.parcelrc')); }, }); @@ -335,13 +1135,10 @@ describe('cache', function() { it('should invalidate when included files changes', async function() { let b = await testCache({ async setup() { - await overlayFS.writeFile( - path.join(__dirname, '/input/src/test.txt'), - 'hi', - ); + await overlayFS.writeFile(path.join(inputDir, 'src/test.txt'), 'hi'); await overlayFS.writeFile( - path.join(__dirname, '/input/src/index.js'), + path.join(inputDir, 'src/index.js'), 'module.exports = require("fs").readFileSync(__dirname + "/test.txt", "utf8")', ); }, @@ -349,7 +1146,7 @@ describe('cache', function() { assert.equal(await run(b.bundleGraph), 'hi'); await overlayFS.writeFile( - path.join(__dirname, '/input/src/test.txt'), + path.join(inputDir, 'src/test.txt'), 'updated', ); }, @@ -361,23 +1158,17 @@ describe('cache', function() { it('should not invalidate when a set environment variable does not change', async () => { let b = await testCache({ async setup() { - await overlayFS.writeFile( - path.join(__dirname, '/input/.env'), - 'TEST=hi', - ); + await overlayFS.writeFile(path.join(inputDir, '.env'), 'TEST=hi'); await overlayFS.writeFile( - path.join(__dirname, '/input/src/index.js'), + path.join(inputDir, 'src/index.js'), 'module.exports = process.env.TEST', ); }, async update(b) { assert.equal(await run(b.bundleGraph), 'hi'); - await overlayFS.writeFile( - path.join(__dirname, '/input/.env'), - 'TEST=hi', - ); + await overlayFS.writeFile(path.join(inputDir, '.env'), 'TEST=hi'); }, }); @@ -389,7 +1180,7 @@ describe('cache', function() { let b = await testCache({ async setup() { await overlayFS.writeFile( - path.join(__dirname, '/input/src/index.js'), + path.join(inputDir, 'src/index.js'), 'module.exports = process.env.TEST', ); }, @@ -406,16 +1197,13 @@ describe('cache', function() { let b = await testCache({ async setup() { await overlayFS.writeFile( - path.join(__dirname, '/input/src/index.js'), + path.join(inputDir, 'src/index.js'), 'module.exports = process.env.TEST', ); }, async update(b) { assert.equal(await run(b.bundleGraph), undefined); - await overlayFS.writeFile( - path.join(__dirname, '/input/.env'), - 'TEST=hi', - ); + await overlayFS.writeFile(path.join(inputDir, '.env'), 'TEST=hi'); }, }); @@ -426,17 +1214,14 @@ describe('cache', function() { let b = await testCache({ async setup() { await overlayFS.writeFile( - path.join(__dirname, '/input/src/index.js'), + path.join(inputDir, 'src/index.js'), 'module.exports = process.env.TEST', ); - await overlayFS.writeFile( - path.join(__dirname, '/input/.env'), - 'TEST=hi', - ); + await overlayFS.writeFile(path.join(inputDir, '.env'), 'TEST=hi'); }, async update(b) { assert.equal(await run(b.bundleGraph), 'hi'); - await overlayFS.writeFile(path.join(__dirname, '/input/.env'), ''); + await overlayFS.writeFile(path.join(inputDir, '.env'), ''); }, }); @@ -446,13 +1231,10 @@ describe('cache', function() { it('should invalidate when environment variables change', async function() { let b = await testCache({ async setup() { - await overlayFS.writeFile( - path.join(__dirname, '/input/.env'), - 'TEST=hi', - ); + await overlayFS.writeFile(path.join(inputDir, '.env'), 'TEST=hi'); await overlayFS.writeFile( - path.join(__dirname, '/input/src/index.js'), + path.join(inputDir, 'src/index.js'), 'module.exports = process.env.TEST', ); }, @@ -460,7 +1242,7 @@ describe('cache', function() { assert.equal(await run(b.bundleGraph), 'hi'); await overlayFS.writeFile( - path.join(__dirname, '/input/.env'), + path.join(inputDir, '.env'), 'TEST=updated', ); }, @@ -487,7 +1269,7 @@ describe('cache', function() { ]); await overlayFS.writeFile( - path.join(__dirname, '/input/src/entries/c.js'), + path.join(inputDir, 'src/entries/c.js'), 'export let c = "c";', ); }, @@ -524,9 +1306,7 @@ describe('cache', function() { }, ]); - await overlayFS.unlink( - path.join(__dirname, '/input/src/entries/b.js'), - ); + await overlayFS.unlink(path.join(inputDir, 'src/entries/b.js')); }, }); @@ -543,13 +1323,13 @@ describe('cache', function() { await assert.rejects( async () => { await testCache(async () => { - await overlayFS.unlink(path.join(__dirname, '/input/src/index.js')); + await overlayFS.unlink(path.join(inputDir, 'src/index.js')); }); }, { message: `Entry ${path.join( - __dirname, - 'input/src/index.js', + inputDir, + 'src/index.js', )} does not exist`, }, ); @@ -560,19 +1340,19 @@ describe('cache', function() { await assert.rejects( async () => { await testCache(async () => { - await overlayFS.unlink(path.join(__dirname, '/input/src/index.js')); + await overlayFS.unlink(path.join(inputDir, 'src/index.js')); }); }, { message: `Entry ${path.join( - __dirname, - 'input/src/index.js', + inputDir, + 'src/index.js', )} does not exist`, }, ); await overlayFS.writeFile( - path.join(__dirname, '/input/src/index.js'), + path.join(inputDir, 'src/index.js'), 'module.exports = "hi"', ); @@ -595,7 +1375,7 @@ describe('cache', function() { 'should not include export default', ); - let pkgFile = path.join(__dirname, '/input/package.json'); + let pkgFile = path.join(inputDir, 'package.json'); let pkg = JSON.parse(await overlayFS.readFile(pkgFile)); await overlayFS.writeFile( pkgFile, @@ -622,7 +1402,7 @@ describe('cache', function() { }); it('should support adding a second target', async function() { - let pkgFile = path.join(__dirname, '/input/package.json'); + let pkgFile = path.join(inputDir, 'package.json'); let b = await testCache({ scopeHoist: true, async setup() { @@ -684,7 +1464,7 @@ describe('cache', function() { }); it('should support changing target output location', async function() { - let pkgFile = path.join(__dirname, '/input/package.json'); + let pkgFile = path.join(inputDir, 'package.json'); await testCache({ scopeHoist: true, async setup() { @@ -712,14 +1492,10 @@ describe('cache', function() { }, async update() { assert( - await overlayFS.exists( - path.join(__dirname, '/input/modern/index.js'), - ), + await overlayFS.exists(path.join(inputDir, 'modern/index.js')), ); assert( - await overlayFS.exists( - path.join(__dirname, '/input/legacy/index.js'), - ), + await overlayFS.exists(path.join(inputDir, 'legacy/index.js')), ); let pkg = JSON.parse(await overlayFS.readFile(pkgFile)); @@ -747,19 +1523,15 @@ describe('cache', function() { }); assert( - await overlayFS.exists( - path.join(__dirname, '/input/dist/modern/index.js'), - ), + await overlayFS.exists(path.join(inputDir, 'dist/modern/index.js')), ); assert( - await overlayFS.exists( - path.join(__dirname, '/input/dist/legacy/index.js'), - ), + await overlayFS.exists(path.join(inputDir, 'dist/legacy/index.js')), ); }); it('should support updating target config options', async function() { - let pkgFile = path.join(__dirname, '/input/package.json'); + let pkgFile = path.join(inputDir, 'package.json'); let b = await testCache({ scopeHoist: true, async setup() { @@ -812,7 +1584,7 @@ describe('cache', function() { }); it('should support deleting a target', async function() { - let pkgFile = path.join(__dirname, '/input/package.json'); + let pkgFile = path.join(inputDir, 'package.json'); let b = await testCache({ scopeHoist: true, async setup() { @@ -874,7 +1646,7 @@ describe('cache', function() { }); it('should support deleting all targets', async function() { - let pkgFile = path.join(__dirname, '/input/package.json'); + let pkgFile = path.join(inputDir, 'package.json'); let b = await testCache({ scopeHoist: true, async setup() { @@ -957,7 +1729,7 @@ describe('cache', function() { }); it('should update when sourcemap options change', async function() { - let pkgFile = path.join(__dirname, '/input/package.json'); + let pkgFile = path.join(inputDir, 'package.json'); let b = await testCache({ scopeHoist: true, async setup() { @@ -1012,7 +1784,7 @@ describe('cache', function() { }); it('should update when publicUrl changes', async function() { - let pkgFile = path.join(__dirname, '/input/package.json'); + let pkgFile = path.join(inputDir, 'package.json'); let b = await testCache({ entries: ['src/index.html'], scopeHoist: true, @@ -1066,7 +1838,7 @@ describe('cache', function() { }); it('should update when a package.json is created', async function() { - let pkgFile = path.join(__dirname, '/input/package.json'); + let pkgFile = path.join(inputDir, 'package.json'); let pkg; let b = await testCache({ scopeHoist: true, @@ -1109,7 +1881,7 @@ describe('cache', function() { }); it('should update when a package.json is deleted', async function() { - let pkgFile = path.join(__dirname, '/input/package.json'); + let pkgFile = path.join(inputDir, 'package.json'); let b = await testCache({ scopeHoist: true, async setup() { @@ -1163,7 +1935,7 @@ describe('cache', function() { 'should include class', ); await overlayFS.writeFile( - path.join(__dirname, '/input/browserslist'), + path.join(inputDir, 'browserslist'), 'IE >= 11', ); }, @@ -1192,7 +1964,7 @@ describe('cache', function() { 'should include class', ); await overlayFS.writeFile( - path.join(__dirname, '/input/.browserslistrc'), + path.join(inputDir, '.browserslistrc'), 'IE >= 11', ); }, @@ -1213,7 +1985,7 @@ describe('cache', function() { scopeHoist: true, async setup() { await overlayFS.writeFile( - path.join(__dirname, '/input/browserslist'), + path.join(inputDir, 'browserslist'), 'IE >= 11', ); }, @@ -1227,7 +1999,7 @@ describe('cache', function() { 'does not include class', ); await overlayFS.writeFile( - path.join(__dirname, '/input/browserslist'), + path.join(inputDir, 'browserslist'), 'last 1 Chrome version', ); }, @@ -1248,7 +2020,7 @@ describe('cache', function() { scopeHoist: true, async setup() { await overlayFS.writeFile( - path.join(__dirname, '/input/browserslist'), + path.join(inputDir, 'browserslist'), 'IE >= 11', ); }, @@ -1261,7 +2033,7 @@ describe('cache', function() { !/class \$[a-f0-9]+\$var\$Test/.test(contents), 'does not include class', ); - await overlayFS.unlink(path.join(__dirname, '/input/browserslist')); + await overlayFS.unlink(path.join(inputDir, 'browserslist')); }, }); @@ -1280,7 +2052,7 @@ describe('cache', function() { scopeHoist: true, async setup() { await overlayFS.writeFile( - path.join(__dirname, '/input/browserslist'), + path.join(inputDir, 'browserslist'), ` [production] IE >= 11 @@ -1323,7 +2095,7 @@ describe('cache', function() { scopeHoist: true, async setup() { await overlayFS.writeFile( - path.join(__dirname, '/input/browserslist'), + path.join(inputDir, 'browserslist'), ` [production] IE >= 11 @@ -1501,7 +2273,7 @@ describe('cache', function() { scopeHoist: true, targets: ['legacy'], async setup() { - let pkgFile = path.join(__dirname, '/input/package.json'); + let pkgFile = path.join(inputDir, 'package.json'); let pkg = JSON.parse(await overlayFS.readFile(pkgFile)); await overlayFS.writeFile( pkgFile, @@ -1661,7 +2433,7 @@ describe('cache', function() { it('should invalidate react refresh hot options change', async function() { let b = await testCache({ async setup() { - let pkgFile = path.join(__dirname, '/input/package.json'); + let pkgFile = path.join(inputDir, 'package.json'); let pkg = JSON.parse(await overlayFS.readFile(pkgFile)); await overlayFS.writeFile( pkgFile, @@ -1674,7 +2446,7 @@ describe('cache', function() { ); await overlayFS.writeFile( - path.join(__dirname, '/input/src/index.js'), + path.join(inputDir, 'src/index.js'), `import React from 'react'; export function Component() { @@ -1721,7 +2493,7 @@ describe('cache', function() { assert(!contents.includes('TRANSFORMED CODE')); await overlayFS.writeFile( - path.join(__dirname, '/input/some-config'), + path.join(inputDir, 'some-config'), JSON.stringify({ extends: '@parcel/config-default', transformers: { @@ -1731,7 +2503,7 @@ describe('cache', function() { ); return { - config: path.join(__dirname, '/input/some-config'), + config: path.join(inputDir, 'some-config'), }; }, }); @@ -1753,7 +2525,7 @@ describe('cache', function() { assert(!contents.includes('TRANSFORMED CODE')); await overlayFS.writeFile( - path.join(__dirname, '/input/some-config'), + path.join(inputDir, 'some-config'), JSON.stringify({ extends: '@parcel/config-default', transformers: { @@ -1763,7 +2535,7 @@ describe('cache', function() { ); return { - defaultConfig: path.join(__dirname, '/input/some-config'), + defaultConfig: path.join(inputDir, 'some-config'), }; }, }); @@ -1817,7 +2589,7 @@ describe('cache', function() { ); assert(contents.includes('INITIAL CODE')); await overlayFS.writeFile( - path.join(__dirname, 'input/dynamic-runtime.js'), + path.join(inputDir, 'dynamic-runtime.js'), "module.exports = 'UPDATED CODE'", ); }, 'runtime-update'); diff --git a/packages/core/integration-tests/test/integration/cache/src/index.js b/packages/core/integration-tests/test/integration/cache/src/index.js index 98020e9b8f8..808ad9e3b6b 100644 --- a/packages/core/integration-tests/test/integration/cache/src/index.js +++ b/packages/core/integration-tests/test/integration/cache/src/index.js @@ -1,3 +1,9 @@ import test from './nested/test'; -module.exports = test + 2; +class Result { + constructor(value) { + this.value = value; + } +} + +module.exports = new Result(test + 2).value; diff --git a/packages/core/integration-tests/test/integration/runtime-update/node_modules/parcel-runtime-mock/index.js b/packages/core/integration-tests/test/integration/runtime-update/node_modules/parcel-runtime-mock/index.js index e1cfd39138c..6d35abe70b7 100644 --- a/packages/core/integration-tests/test/integration/runtime-update/node_modules/parcel-runtime-mock/index.js +++ b/packages/core/integration-tests/test/integration/runtime-update/node_modules/parcel-runtime-mock/index.js @@ -4,7 +4,7 @@ const path = require('path'); module.exports = new Runtime({ apply() { return [{ - filePath: path.resolve(__dirname, '../../../input/MockRuntime.js'), + filePath: path.resolve(__dirname, '../../MockRuntime.js'), code: `let x = require('./dynamic-runtime'); console.log(x);`, isEntry: true }] diff --git a/packages/core/is-v2-ready-yet/package.json b/packages/core/is-v2-ready-yet/package.json index 493607489ff..b28d42fcd1c 100644 --- a/packages/core/is-v2-ready-yet/package.json +++ b/packages/core/is-v2-ready-yet/package.json @@ -19,7 +19,7 @@ "victory": "^31.0.1" }, "devDependencies": { - "@babel/core": "^7.2.0", + "@babel/core": "^7.12.0", "@babel/plugin-proposal-class-properties": "^7.2.1", "@babel/preset-env": "^7.2.0", "@babel/preset-react": "^7.0.0" diff --git a/packages/core/register/example/package.json b/packages/core/register/example/package.json index fd448c9ab1e..44b5746e189 100644 --- a/packages/core/register/example/package.json +++ b/packages/core/register/example/package.json @@ -7,7 +7,7 @@ "start": "node ./index.js" }, "dependencies": { - "@babel/core": "^7.2.0", + "@babel/core": "^7.12.0", "something": "1.0.0" } } diff --git a/packages/core/test-utils/src/utils.js b/packages/core/test-utils/src/utils.js index 812152093a0..bc8ee28e03b 100644 --- a/packages/core/test-utils/src/utils.js +++ b/packages/core/test-utils/src/utils.js @@ -9,6 +9,7 @@ import type { InitialParcelOptions, NamedBundle, } from '@parcel/types'; +import type WorkerFarm from '@parcel/workers'; import invariant from 'assert'; import util from 'util'; @@ -29,7 +30,7 @@ import _chalk from 'chalk'; import resolve from 'resolve'; import {NodePackageManager} from '@parcel/package-manager'; -const workerFarm = createWorkerFarm(); +export const workerFarm = (createWorkerFarm(): WorkerFarm); export const inputFS: NodeFS = new NodeFS(); export let outputFS: MemoryFS = new MemoryFS(workerFarm); export let overlayFS: OverlayFS = new OverlayFS(outputFS, inputFS); diff --git a/packages/core/workers/src/WorkerFarm.js b/packages/core/workers/src/WorkerFarm.js index 1e898a222e8..c904eb07d46 100644 --- a/packages/core/workers/src/WorkerFarm.js +++ b/packages/core/workers/src/WorkerFarm.js @@ -493,6 +493,26 @@ export default class WorkerFarm extends EventEmitter { }); } + async callAllWorkers(method: string, args: Array) { + let promises = []; + for (let worker of this.workers.values()) { + promises.push( + new Promise((resolve, reject) => { + worker.call({ + method, + args, + resolve, + reject, + retries: 0, + }); + }), + ); + } + + promises.push(this.localWorker[method](this.workerApi, ...args)); + await Promise.all(promises); + } + async takeHeapSnapshot() { let snapshotId = getTimeId(); diff --git a/packages/dev/babel-preset/package.json b/packages/dev/babel-preset/package.json index 960548ba54e..99855323ba7 100644 --- a/packages/dev/babel-preset/package.json +++ b/packages/dev/babel-preset/package.json @@ -16,6 +16,6 @@ "read-pkg-up": "^4.0.0" }, "devDependencies": { - "@babel/core": "^7.7.0" + "@babel/core": "^7.12.0" } } diff --git a/packages/dev/eslint-config-browser/index.js b/packages/dev/eslint-config-browser/index.js index dae78cd1c88..030f5f91863 100644 --- a/packages/dev/eslint-config-browser/index.js +++ b/packages/dev/eslint-config-browser/index.js @@ -1,6 +1,6 @@ module.exports = { extends: '@parcel/eslint-config', - parser: 'babel-eslint', + parser: '@babel/eslint-parser', parserOptions: { ecmaVersion: 5, }, diff --git a/packages/dev/eslint-config/index.js b/packages/dev/eslint-config/index.js index 91714183924..0abfa81961a 100644 --- a/packages/dev/eslint-config/index.js +++ b/packages/dev/eslint-config/index.js @@ -8,7 +8,7 @@ module.exports = { 'prettier/flowtype', 'prettier/react', ], - parser: 'babel-eslint', + parser: '@babel/eslint-parser', plugins: ['@parcel', 'flowtype', 'import', 'monorepo', 'react', 'mocha'], parserOptions: { ecmaVersion: 2018, diff --git a/packages/dev/eslint-config/package.json b/packages/dev/eslint-config/package.json index f95a926aaac..b1f20d0d727 100644 --- a/packages/dev/eslint-config/package.json +++ b/packages/dev/eslint-config/package.json @@ -3,8 +3,8 @@ "private": true, "version": "2.0.0-beta.1", "dependencies": { + "@babel/eslint-parser": "^7.12.1", "@parcel/eslint-plugin": "2.0.0-beta.1", - "babel-eslint": "^10.0.1", "eslint-config-prettier": "^4.1.0", "eslint-plugin-flowtype": "^3.1.1", "eslint-plugin-import": "^2.16.0", diff --git a/packages/dev/eslint-plugin/package.json b/packages/dev/eslint-plugin/package.json index 79b9cdbc497..074b9a98a15 100644 --- a/packages/dev/eslint-plugin/package.json +++ b/packages/dev/eslint-plugin/package.json @@ -8,7 +8,7 @@ "read-pkg-up": "^5.0.0" }, "devDependencies": { - "babel-eslint": "^10.0.1", + "@babel/eslint-parser": "^7.12.1", "eslint": "^5.16.0" } } diff --git a/packages/dev/eslint-plugin/test/rules/no-self-package-imports.test.js b/packages/dev/eslint-plugin/test/rules/no-self-package-imports.test.js index 3a87daf132d..4595d376c5f 100644 --- a/packages/dev/eslint-plugin/test/rules/no-self-package-imports.test.js +++ b/packages/dev/eslint-plugin/test/rules/no-self-package-imports.test.js @@ -9,7 +9,7 @@ const message = const filename = __filename; new RuleTester({ - parser: 'babel-eslint', + parser: '@babel/eslint-parser', parserOptions: {ecmaVersion: 2018, sourceType: 'module'}, }).run('no-self-package-imports', rule, { valid: [ diff --git a/packages/dev/eslint-plugin/test/utils.test.js b/packages/dev/eslint-plugin/test/utils.test.js index 3455a939b18..e9e2cab6b6d 100644 --- a/packages/dev/eslint-plugin/test/utils.test.js +++ b/packages/dev/eslint-plugin/test/utils.test.js @@ -2,7 +2,7 @@ const assert = require('assert'); const path = require('path'); -const {parse} = require('babel-eslint'); +const {parse} = require('@babel/eslint-parser'); const readPkgUp = require('read-pkg-up'); const { diff --git a/packages/reporters/cli/src/CLIReporter.js b/packages/reporters/cli/src/CLIReporter.js index 55d2e895364..a3d36b6c881 100644 --- a/packages/reporters/cli/src/CLIReporter.js +++ b/packages/reporters/cli/src/CLIReporter.js @@ -20,6 +20,7 @@ import { import * as emoji from './emoji'; const THROTTLE_DELAY = 100; +const seenWarnings = new Set(); let statusThrottle = throttle((message: string) => { updateSpinner(message); @@ -34,6 +35,7 @@ export async function _report( switch (event.type) { case 'buildStart': { + seenWarnings.clear(); if (logLevelFilter < logLevels.info) { break; } @@ -116,7 +118,16 @@ export async function _report( await writeDiagnostic(options, event.diagnostics, 'blue'); break; case 'warn': - await writeDiagnostic(options, event.diagnostics, 'yellow', true); + if ( + event.diagnostics.some( + diagnostic => !seenWarnings.has(diagnostic.message), + ) + ) { + await writeDiagnostic(options, event.diagnostics, 'yellow', true); + for (let diagnostic of event.diagnostics) { + seenWarnings.add(diagnostic.message); + } + } break; case 'error': await writeDiagnostic(options, event.diagnostics, 'red', true); diff --git a/packages/reporters/cli/test/CLIReporter.test.js b/packages/reporters/cli/test/CLIReporter.test.js index c5a073c9728..94d6c078ac7 100644 --- a/packages/reporters/cli/test/CLIReporter.test.js +++ b/packages/reporters/cli/test/CLIReporter.test.js @@ -39,7 +39,7 @@ describe('CLIReporter', () => { let stdoutOutput; let stderrOutput; - beforeEach(() => { + beforeEach(async () => { // Stub these out to avoid writing noise to real stdio and to read from these // otherwise only writable streams originalStdout = process.stdout; @@ -53,6 +53,13 @@ describe('CLIReporter', () => { let mockStderr = new PassThrough(); mockStderr.on('data', d => (stderrOutput += stripAnsi(d.toString()))); _setStdio(mockStdout, mockStderr); + + await _report( + { + type: 'buildStart', + }, + EMPTY_OPTIONS, + ); }); afterEach(() => { diff --git a/packages/resolvers/default/package.json b/packages/resolvers/default/package.json index 6851bd17b6f..5d4b48da20e 100644 --- a/packages/resolvers/default/package.json +++ b/packages/resolvers/default/package.json @@ -23,6 +23,6 @@ "@parcel/plugin": "2.0.0-beta.1" }, "devDependencies": { - "@babel/core": "^7.2.2" + "@babel/core": "^7.12.2" } } diff --git a/packages/transformers/babel/package.json b/packages/transformers/babel/package.json index a9c77c8ac21..1dbeb5590e3 100644 --- a/packages/transformers/babel/package.json +++ b/packages/transformers/babel/package.json @@ -20,7 +20,7 @@ "parcel": "^2.0.0-alpha.1.1" }, "dependencies": { - "@babel/core": "^7.0.0", + "@babel/core": "^7.12.0", "@babel/generator": "^7.0.0", "@babel/helper-compilation-targets": "^7.8.4", "@babel/plugin-transform-flow-strip-types": "^7.0.0", diff --git a/packages/transformers/babel/src/config.js b/packages/transformers/babel/src/config.js index e1a403a508b..65d8d369e2c 100644 --- a/packages/transformers/babel/src/config.js +++ b/packages/transformers/babel/src/config.js @@ -8,6 +8,7 @@ import nullthrows from 'nullthrows'; import path from 'path'; import * as bundledBabelCore from '@babel/core'; import {md5FromObject, resolveConfig} from '@parcel/utils'; +import semver from 'semver'; import getEnvOptions from './env'; import getJSXOptions from './jsx'; @@ -18,6 +19,7 @@ import {BABEL_RANGE} from './constants'; const TYPESCRIPT_EXTNAME_RE = /^\.tsx?/; const BABEL_TRANSFORMER_DIR = path.dirname(__dirname); +const JS_EXTNAME_RE = /^\.(js|cjs|mjs)$/; export async function load( config: Config, @@ -43,13 +45,16 @@ export async function load( } } - let babelCore = await options.packageManager.require( + let resolved = await options.packageManager.resolve( '@babel/core', config.searchPath, {range: BABEL_RANGE, autoinstall: options.autoinstall}, ); - - let partialConfig = babelCore.loadPartialConfig({ + let babelCore = await options.packageManager.require( + resolved.resolved, + config.searchPath, + ); + let babelOptions = { filename: config.searchPath, cwd: path.dirname(config.searchPath), root: options.projectRoot, @@ -61,10 +66,75 @@ export async function load( ? options.mode : null) ?? 'development', - }); + }; + + // Only add the showIgnoredFiles option if babel is new enough, otherwise it will throw on unknown option. + if (semver.satisfies(nullthrows(resolved.pkg).version, '^7.12.0')) { + // $FlowFixMe + babelOptions.showIgnoredFiles = true; + } + + let partialConfig: ?{| + [string]: any, + |} = await babelCore.loadPartialConfigAsync(babelOptions); + + // Invalidate when any babel config file is added. + config.setWatchGlob( + '**/{.babelrc,.babelrc.js,.babelrc.json,.babelrc.cjs,.babelrc.mjs,.babelignore,babel.config.js,babel.config.json,babel.config.mjs,babel.config.cjs}', + ); + + let addIncludedFile = file => { + if (JS_EXTNAME_RE.test(path.extname(file))) { + logger.warn({ + message: `It looks like you're using a JavaScript Babel config file. This means the config cannot be watched for changes, and Babel transformations cannot be cached. You'll need to restart Parcel for changes to this config to take effect. Try using a ${path.basename( + file, + path.extname(file), + ) + '.json'} file instead.`, + }); + config.shouldInvalidateOnStartup(); + } else { + config.addIncludedFile(file); + } + }; - // loadPartialConfig returns null when the file should explicitly not be run through babel (ignore/exclude) + let warnOldVersion = () => { + logger.warn({ + message: + 'You are using an old version of @babel/core which does not support the necessary features for Parcel to cache and watch babel config files safely. You may need to restart Parcel for config changes to take effect. Please upgrade to @babel/core 7.12.0 or later to resolve this issue.', + }); + config.shouldInvalidateOnStartup(); + }; + + // Old versions of @babel/core return null from loadPartialConfig when the file should explicitly not be run through babel (ignore/exclude) if (partialConfig == null) { + warnOldVersion(); + return; + } + + if (partialConfig.files == null) { + // If the files property is missing, we're on an old version of @babel/core. + // We need to invalidate on startup because we can't properly track dependencies. + if (partialConfig.hasFilesystemConfig()) { + warnOldVersion(); + + if (typeof partialConfig.babelrcPath === 'string') { + addIncludedFile(partialConfig.babelrcPath); + } + + if (typeof partialConfig.configPath === 'string') { + addIncludedFile(partialConfig.configPath); + } + } + } else { + for (let file of partialConfig.files) { + addIncludedFile(file); + } + } + + if ( + partialConfig.fileHandling != null && + partialConfig.fileHandling !== 'transpile' + ) { return; } else if (partialConfig.hasFilesystemConfig()) { config.setResult({ @@ -73,54 +143,30 @@ export async function load( targets: enginesToBabelTargets(config.env), }); - let {babelrc: babelrcPath, config: configPath} = partialConfig; - let {canBeRehydrated, dependsOnRelative, dependsOnLocal} = getStats( - partialConfig.options, - ); - - let configIsJS = - (typeof babelrcPath === 'string' && - path.extname(babelrcPath) === '.js') || - (typeof configPath === 'string' && path.extname(configPath) === '.js'); + let {hasRequire, dependsOnLocal} = getStats(partialConfig.options, options); - if (configIsJS) { - logger.verbose({ - message: - 'WARNING: Using a JavaScript Babel config file means losing out on some caching features of Parcel. Try using a .babelrc file instead.', - }); + // If the config depends on local plugins or has plugins loaded with require(), + // we can't cache the result of the compilation. If the config references local plugins, + // we can't know what dependencies those plugins might have. If the config has require() + // calls in it to load plugins we can't know where they came from. + if (dependsOnLocal || hasRequire) { + config.setResultHash(JSON.stringify(Date.now())); config.shouldInvalidateOnStartup(); - // babel.config.js files get required by @babel/core so there's no use in setting resolved path for watch mode invalidation - } else { - config.addIncludedFile( - typeof babelrcPath === 'string' ? babelrcPath : configPath, - ); } - if (babelrcPath && (await isExtended(/* babelrcPath */))) { - logger.verbose({ + if (dependsOnLocal) { + logger.warn({ message: - 'WARNING: You are using `extends` in your Babel config, which means you are losing out on some of the caching features of Parcel. Maybe try using a reusable preset instead.', + "It looks like you are using local Babel plugins or presets. This means Babel transformations cannot be cached and will run on each build. You'll need to restart Parcel for changes to local plugins to take effect.", }); - config.shouldInvalidateOnStartup(); - } - - if (dependsOnRelative || dependsOnLocal) { - logger.verbose({ + } else if (hasRequire) { + logger.warn({ message: - 'WARNING: It looks like you are using local Babel plugins or presets. You will need to run with the `--no-cache` option in order to pick up changes to these until their containing package versions are bumped.', + 'It looks like you are using `require` to configure Babel plugins or presets. This means Babel transformations cannot be cached and will run on each build. Please use strings to configure Babel instead.', }); - } - - if (canBeRehydrated) { + } else { await definePluginDependencies(config); config.setResultHash(md5FromObject(partialConfig.options)); - } else { - logger.verbose({ - message: - 'WARNING: You are using `require` to configure Babel plugins or presets. This means Babel transformations cannot be cached and will run on each build. Please use strings to configure Babel instead.', - }); - config.setResultHash(JSON.stringify(Date.now())); - config.shouldInvalidateOnStartup(); } } else { await buildDefaultBabelConfig(options, config); @@ -189,39 +235,32 @@ function mergeOptions(result, config?: null | BabelConfig) { return result; } -function getStats(options) { - let canBeRehydrated = true; - let dependsOnRelative = false; +function getStats(options, parcelOptions) { + let hasRequire = false; let dependsOnLocal = false; let configItems = [...options.presets, ...options.plugins]; for (let configItem of configItems) { if (!configItem.file) { - canBeRehydrated = false; - } else if (configItem.file.request.startsWith('.')) { - dependsOnRelative = true; - } else if (isLocal(/*configItem.file.resolved*/)) { + hasRequire = true; + } else if ( + configItem.file.request.startsWith('.') || + isLocal(configItem.file.resolved, parcelOptions.inputFS) + ) { dependsOnLocal = true; } } - return {canBeRehydrated, dependsOnRelative, dependsOnLocal}; + return {hasRequire, dependsOnLocal}; } -function isExtended(/* babelrcPath */) { - // TODO: read and parse babelrc and check to see if extends property exists - // need access to fs in case of memory filesystem - return false; -} - -function isLocal(/* configItemPath */) { - // TODO: check if realpath is different, need access to fs in case of memory filesystem - return false; +function isLocal(configItemPath, fs) { + return fs.realpathSync(configItemPath) !== configItemPath; } export function preSerialize(config: Config) { - let babelConfig = config.result.config; + let babelConfig = config.result?.config; if (babelConfig == null) { return; } diff --git a/packages/transformers/js/package.json b/packages/transformers/js/package.json index ffd155a5ef6..b99e8f5a691 100644 --- a/packages/transformers/js/package.json +++ b/packages/transformers/js/package.json @@ -20,7 +20,7 @@ "parcel": "^2.0.0-alpha.1.1" }, "dependencies": { - "@babel/core": "^7.0.0", + "@babel/core": "^7.12.0", "@babel/generator": "^7.0.0", "@babel/parser": "^7.0.0", "@babel/plugin-transform-modules-commonjs": "^7.0.0", diff --git a/packages/transformers/postcss/src/PostCSSTransformer.js b/packages/transformers/postcss/src/PostCSSTransformer.js index 55e12f8f737..1f53c1bde21 100644 --- a/packages/transformers/postcss/src/PostCSSTransformer.js +++ b/packages/transformers/postcss/src/PostCSSTransformer.js @@ -123,13 +123,6 @@ export default (new Transformer({ }); for (let msg of messages) { if (msg.type === 'dependency') { - msg = (msg: {| - type: 'dependency', - plugin: string, - file: string, - parent: string, - |}); - asset.addIncludedFile(msg.file); } } diff --git a/packages/utils/babel-plugin-transform-runtime/package.json b/packages/utils/babel-plugin-transform-runtime/package.json index 6008607ac84..123dcb893a3 100644 --- a/packages/utils/babel-plugin-transform-runtime/package.json +++ b/packages/utils/babel-plugin-transform-runtime/package.json @@ -22,7 +22,7 @@ "semver": "^5.4.1" }, "devDependencies": { - "@babel/core": "^7.4.4", + "@babel/core": "^7.12.0", "@parcel/babel-preset-env": "2.0.0-beta.1" } } diff --git a/packages/utils/babel-preset-env/package.json b/packages/utils/babel-preset-env/package.json index 1ddb33bcc85..eaabee73493 100644 --- a/packages/utils/babel-preset-env/package.json +++ b/packages/utils/babel-preset-env/package.json @@ -22,9 +22,9 @@ "semver": "^5.4.1" }, "devDependencies": { - "@babel/core": "^7.4.4" + "@babel/core": "^7.12.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.12.0" } } diff --git a/yarn.lock b/yarn.lock index 80d3216135a..97468acae70 100644 --- a/yarn.lock +++ b/yarn.lock @@ -55,7 +55,29 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.0.0", "@babel/core@^7.2.0", "@babel/core@^7.2.2", "@babel/core@^7.4.4", "@babel/core@^7.7.0", "@babel/core@^7.8.7": +"@babel/core@^7.12.0", "@babel/core@^7.12.2": + version "7.12.3" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.3.tgz#1b436884e1e3bff6fb1328dc02b208759de92ad8" + integrity sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.1" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.1" + "@babel/parser" "^7.12.3" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@^7.4.4": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w== @@ -77,7 +99,16 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.0.0", "@babel/generator@^7.3.3", "@babel/generator@^7.4.4", "@babel/generator@^7.8.0", "@babel/generator@^7.9.0", "@babel/generator@^7.9.5": +"@babel/eslint-parser@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.12.1.tgz#b3ae38e6174d2d0d2d00d2dcd919b4086b6bb8f0" + integrity sha512-cc7WQHnHQY3++/bghgbDtPx+5bf6xTsokyGzV6Qzh65NLz/unv+mPQuACkQ9GFhIhcTFv6yqwNaEcfX7EkOEsg== + dependencies: + eslint-scope "5.1.0" + eslint-visitor-keys "^1.3.0" + semver "^6.3.0" + +"@babel/generator@^7.0.0", "@babel/generator@^7.3.3", "@babel/generator@^7.4.4", "@babel/generator@^7.8.0": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9" integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ== @@ -87,6 +118,15 @@ lodash "^4.17.13" source-map "^0.5.0" +"@babel/generator@^7.12.1", "@babel/generator@^7.9.0", "@babel/generator@^7.9.5": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.1.tgz#0d70be32bdaa03d7c51c8597dda76e0df1f15468" + integrity sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg== + dependencies: + "@babel/types" "^7.12.1" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" @@ -168,7 +208,16 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-function-name@^7.8.3", "@babel/helper-function-name@^7.9.5": +"@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.9.5": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== + dependencies: + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-function-name@^7.8.3": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw== @@ -177,12 +226,12 @@ "@babel/template" "^7.8.3" "@babel/types" "^7.9.5" -"@babel/helper-get-function-arity@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" - integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== +"@babel/helper-get-function-arity@^7.10.4", "@babel/helper-get-function-arity@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.10.4" "@babel/helper-hoist-variables@^7.8.3": version "7.8.3" @@ -191,39 +240,41 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-member-expression-to-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" - integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== +"@babel/helper-member-expression-to-functions@^7.12.1", "@babel/helper-member-expression-to-functions@^7.8.3": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz#fba0f2fcff3fba00e6ecb664bb5e6e26e2d6165c" + integrity sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.12.1" -"@babel/helper-module-imports@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" - integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== +"@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.8.3": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.1.tgz#1644c01591a15a2f084dd6d092d9430eb1d1216c" + integrity sha512-ZeC1TlMSvikvJNy1v/wPIazCu3NdOwgYZLIkmIyAsGhqkNpiDoQQRmaCK8YP4Pq3GPTLPV9WXaPCJKvx06JxKA== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.12.1" -"@babel/helper-module-transforms@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5" - integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.9.0": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" + integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-simple-access" "^7.8.3" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/template" "^7.8.6" - "@babel/types" "^7.9.0" - lodash "^4.17.13" + "@babel/helper-module-imports" "^7.12.1" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-simple-access" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/helper-validator-identifier" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + lodash "^4.17.19" -"@babel/helper-optimise-call-expression@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" - integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== +"@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.10.4" "@babel/helper-plugin-utils@7.8.0": version "7.8.0" @@ -258,7 +309,17 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-replace-supers@^7.8.3", "@babel/helper-replace-supers@^7.8.6": +"@babel/helper-replace-supers@^7.12.1", "@babel/helper-replace-supers@^7.8.6": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.1.tgz#f15c9cc897439281891e11d5ce12562ac0cf3fa9" + integrity sha512-zJjTvtNJnCFsCXVi5rUInstLd/EIVNmIKA1Q9ynESmMBWPWd+7sdR+G4/wdu+Mppfep0XLyG2m7EBPvjCeFyrw== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.12.1" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + +"@babel/helper-replace-supers@^7.8.3": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8" integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA== @@ -268,20 +329,19 @@ "@babel/traverse" "^7.8.6" "@babel/types" "^7.8.6" -"@babel/helper-simple-access@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" - integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw== +"@babel/helper-simple-access@^7.12.1", "@babel/helper-simple-access@^7.8.3": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" + integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== dependencies: - "@babel/template" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/types" "^7.12.1" -"@babel/helper-split-export-declaration@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" - integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== +"@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.8.3": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.11.0" "@babel/helper-validator-identifier@^7.10.4": version "7.10.4" @@ -298,7 +358,16 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helpers@^7.8.0", "@babel/helpers@^7.9.0": +"@babel/helpers@^7.12.1", "@babel/helpers@^7.9.0": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.1.tgz#8a8261c1d438ec18cb890434df4ec768734c1e79" + integrity sha512-9JoDSBGoWtmbay98efmT2+mySkwjzeFeAL9BuWNoVQpkPFQF8SIIFUfY5os9u8wVzglzoiPRSW7cuJmBDUt43g== + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + +"@babel/helpers@^7.8.0": version "7.9.2" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f" integrity sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA== @@ -316,11 +385,16 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.10.4", "@babel/parser@^7.4.4", "@babel/parser@^7.8.0", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0": +"@babel/parser@^7.0.0", "@babel/parser@^7.4.4", "@babel/parser@^7.8.0", "@babel/parser@^7.8.6": version "7.11.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037" integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q== +"@babel/parser@^7.10.4", "@babel/parser@^7.12.1", "@babel/parser@^7.12.3", "@babel/parser@^7.9.0": + version "7.12.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.3.tgz#a305415ebe7a6c7023b40b5122a0662d928334cd" + integrity sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw== + "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" @@ -966,7 +1040,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.4.0", "@babel/template@^7.4.4", "@babel/template@^7.8.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6": +"@babel/template@^7.10.4", "@babel/template@^7.4.0", "@babel/template@^7.4.4", "@babel/template@^7.8.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== @@ -975,7 +1049,7 @@ "@babel/parser" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.2.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.8.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": +"@babel/traverse@^7.0.0", "@babel/traverse@^7.2.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.8.0", "@babel/traverse@^7.8.3": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2" integrity sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ== @@ -990,7 +1064,22 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.8.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5": +"@babel/traverse@^7.12.1", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.1.tgz#941395e0c5cc86d5d3e75caa095d3924526f0c1e" + integrity sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.1" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.12.1" + "@babel/types" "^7.12.1" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + +"@babel/types@^7.0.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.8.0": version "7.11.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q== @@ -999,6 +1088,15 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.1.tgz#e109d9ab99a8de735be287ee3d6a9947a190c4ae" + integrity sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@choojs/findup@^0.2.0": version "0.2.1" resolved "https://registry.yarnpkg.com/@choojs/findup/-/findup-0.2.1.tgz#ac13c59ae7be6e1da64de0779a0a7f03d75615a3" @@ -2763,18 +2861,6 @@ babel-code-frame@^6.26.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-eslint@^10.0.1: - version "10.0.3" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a" - integrity sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.0.0" - "@babel/traverse" "^7.0.0" - "@babel/types" "^7.0.0" - eslint-visitor-keys "^1.0.0" - resolve "^1.12.0" - babel-generator@^6.18.0: version "6.26.1" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" @@ -4906,7 +4992,7 @@ debug-log@^1.0.1: resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" integrity sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8= -debug@*, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: +debug@*, debug@^4.0.1, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -4934,6 +5020,13 @@ debug@3.2.6, debug@^3.0.0, debug@^3.1.0: dependencies: ms "^2.1.1" +debug@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + dependencies: + ms "2.1.2" + debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -5611,6 +5704,14 @@ eslint-plugin-react@^7.12.0: prop-types "^15.7.2" resolve "^1.14.2" +eslint-scope@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" + integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + eslint-scope@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" @@ -5639,6 +5740,11 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== +eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + eslint@^5.16.0: version "5.16.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" @@ -9488,7 +9594,7 @@ ms@2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== -ms@^2.0.0, ms@^2.1.1: +ms@2.1.2, ms@^2.0.0, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -12175,13 +12281,20 @@ resolve@^0.6.1: resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46" integrity sha1-3ZV5gufnNt699TtYpN2RdUV13UY= -resolve@^1.0.0, resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.8.1: +resolve@^1.0.0, resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.4.0, resolve@^1.8.1: version "1.15.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.0.tgz#1b7ca96073ebb52e741ffd799f6b39ea462c67f5" integrity sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw== dependencies: path-parse "^1.0.6" +resolve@^1.3.2: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"