diff --git a/packages/babel-cli/src/babel/dir.ts b/packages/babel-cli/src/babel/dir.ts index 5bbbec2886e5..c65536a3e93f 100644 --- a/packages/babel-cli/src/babel/dir.ts +++ b/packages/babel-cli/src/babel/dir.ts @@ -177,34 +177,70 @@ export default async function ({ // This, alongside with debounce, allows us to only log // when we are sure that all the files have been compiled. let processing = 0; + const { filenames } = cliOptions; + let getBase; + if (filenames.length === 1) { + // fast path: If there is only one filenames, we know it must be the base + const base = filenames[0]; + const absoluteBase = path.resolve(base); + getBase = filename => { + return filename === absoluteBase ? path.dirname(base) : base; + }; + } else { + // A map from absolute compiled file path to its base, from which + // the output destination will be determined + const filenameToBaseMap: Map = new Map( + filenames.map(filename => { + const absoluteFilename = path.resolve(filename); + return [absoluteFilename, path.dirname(filename)]; + }), + ); + + const absoluteFilenames: Map = new Map( + filenames.map(filename => { + const absoluteFilename = path.resolve(filename); + return [absoluteFilename, filename]; + }), + ); + + const { sep } = path; + // determine base from the absolute file path + getBase = filename => { + const base = filenameToBaseMap.get(filename); + if (base !== undefined) { + return base; + } + for (const [absoluteFilenameOrDir, relative] of absoluteFilenames) { + if (filename.startsWith(absoluteFilenameOrDir + sep)) { + filenameToBaseMap.set(filename, relative); + return relative; + } + } + // Can't determine the base, probably external deps + return ""; + }; + } - cliOptions.filenames.forEach(filenameOrDir => { + filenames.forEach(filenameOrDir => { watcher.watch(filenameOrDir); + }); - watcher.onFilesChange(async filenames => { - processing++; - if (startTime === null) startTime = process.hrtime(); - - try { - const written = await Promise.all( - filenames.map(filename => - handleFile( - filename, - filename === filenameOrDir - ? path.dirname(filenameOrDir) - : filenameOrDir, - ), - ), - ); - - compiledFiles += written.filter(Boolean).length; - } catch (err) { - console.error(err); - } + watcher.onFilesChange(async filenames => { + processing++; + if (startTime === null) startTime = process.hrtime(); - processing--; - if (processing === 0 && !cliOptions.quiet) logSuccess(); - }); + try { + const written = await Promise.all( + filenames.map(filename => handleFile(filename, getBase(filename))), + ); + + compiledFiles += written.filter(Boolean).length; + } catch (err) { + console.error(err); + } + + processing--; + if (processing === 0 && !cliOptions.quiet) logSuccess(); }); } } diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch --verbose with external dependencies/executor.js b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch --verbose with external dependencies/executor.js index 06acdf07b0cf..fcf460a0347b 100644 --- a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch --verbose with external dependencies/executor.js +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch --verbose with external dependencies/executor.js @@ -4,7 +4,7 @@ const assert = require("assert"); // For Node.js <= 10 if (!assert.match) assert.match = (val, re) => assert(re.test(val)); -const run = (function* () { +const run = (async function* () { let files = [yield, yield].sort(); assert.match(files[0], /src[\\/]index.js -> lib[\\/]index.js/); assert.match(files[1], /src[\\/]main.js -> lib[\\/]main.js/); @@ -12,7 +12,8 @@ const run = (function* () { logFile("lib/index.js"); logFile("lib/main.js"); - + // wait 200ms for watcher setup + await new Promise(resolve => setTimeout(resolve, 200)); fs.writeFileSync("./file.txt", "Updated!"); files = [yield, yield].sort(); @@ -29,7 +30,7 @@ run.next(); const batchedStrings = []; let batchId = 0; -process.stdin.on("data", function listener(chunk) { +process.stdin.on("data", async function listener(chunk) { const str = String(chunk).trim(); if (!str) return; @@ -50,7 +51,7 @@ process.stdin.on("data", function listener(chunk) { console.log(str); } - if (run.next(str).done) { + if ((await run.next(str)).done) { process.exit(0); } }); diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch --verbose with external dependencies/options.json b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch --verbose with external dependencies/options.json index 6fc02e90636e..b29801fb5518 100644 --- a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch --verbose with external dependencies/options.json +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch --verbose with external dependencies/options.json @@ -2,5 +2,5 @@ "args": ["src", "--out-dir", "lib", "--watch", "--verbose"], "noBabelrc": true, "noDefaultPlugins": true, - "minNodeVersion": 8 + "minNodeVersion": 10 } diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/executor.js b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/executor.js new file mode 100644 index 000000000000..1d480afb2637 --- /dev/null +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/executor.js @@ -0,0 +1,37 @@ +const fs = require("fs"); +const assert = require("assert"); + +// For Node.js <= 10 +if (!assert.match) assert.match = (val, re) => assert(re.test(val)); + +const run = (async function* () { + assert.match(yield, /Successfully compiled 4 files with Babel \(\d+ms\)\./); + + // wait 200ms for watcher setup + await new Promise(resolve => setTimeout(resolve, 200)); + // update ./module1/src/index.js + fs.writeFileSync( + "./module1/src/index.js", + `let str = REPLACE_ME + REPLACE_ME;` + ); + + assert.match(yield, /Successfully compiled 1 file with Babel \(\d+ms\)\./); +})(); + +run.next(); + +process.stdin.on("data", async function listener(chunk) { + const str = String(chunk).trim(); + if (!str) return; + + console.log(str); + + if ((await run.next(str)).done) { + process.exit(0); + } +}); + +setTimeout(() => { + console.error("EXECUTOR TIMEOUT"); + process.exit(1); +}, 5000); diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/babel.config.cjs b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/babel.config.cjs new file mode 100644 index 000000000000..82a7bc963ce6 --- /dev/null +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/babel.config.cjs @@ -0,0 +1,25 @@ +const fs = require("fs"); +const path = require("path"); + +function inlinePlugin(api, { filename }) { + const { types: t } = api; + + const contents = api.cache.using(() => fs.readFileSync(filename, "utf8")); + api.addExternalDependency(filename); + + return { + visitor: { + Identifier(path) { + if (path.node.name === "REPLACE_ME") { + path.replaceWith(t.stringLiteral(contents)); + } + }, + }, + }; +} + +module.exports = { + plugins: [ + [inlinePlugin, { filename: path.resolve(__dirname, "./file.txt") }], + ], +}; diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/file.txt b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/file.txt new file mode 100644 index 000000000000..50f9dc495c1e --- /dev/null +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/file.txt @@ -0,0 +1 @@ +Hi :) diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/module1/src/index.js b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/module1/src/index.js new file mode 100644 index 000000000000..32fcf9431c12 --- /dev/null +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/module1/src/index.js @@ -0,0 +1 @@ +let str = REPLACE_ME; diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/module1/src/main.js b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/module1/src/main.js new file mode 100644 index 000000000000..97ecfbae3a71 --- /dev/null +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/module1/src/main.js @@ -0,0 +1 @@ +console.log(REPLACE_ME); diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/module2/src/index.js b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/module2/src/index.js new file mode 100644 index 000000000000..32fcf9431c12 --- /dev/null +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/module2/src/index.js @@ -0,0 +1 @@ +let str = REPLACE_ME; diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/module2/src/main.js b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/module2/src/main.js new file mode 100644 index 000000000000..97ecfbae3a71 --- /dev/null +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/in-files/module2/src/main.js @@ -0,0 +1 @@ +console.log(REPLACE_ME); diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/options.json b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/options.json new file mode 100644 index 000000000000..0e04683004f1 --- /dev/null +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/options.json @@ -0,0 +1,6 @@ +{ + "args": ["*/src", "--out-dir", "../lib", "--relative", "--watch"], + "noBabelrc": true, + "noDefaultPlugins": true, + "minNodeVersion": 10 +} diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/out-files/module1/lib/index.js b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/out-files/module1/lib/index.js new file mode 100644 index 000000000000..4d75d33908a9 --- /dev/null +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/out-files/module1/lib/index.js @@ -0,0 +1 @@ +let str = "Hi :)" + "Hi :)"; diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/out-files/module1/lib/main.js b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/out-files/module1/lib/main.js new file mode 100644 index 000000000000..b0d766e0fe27 --- /dev/null +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/out-files/module1/lib/main.js @@ -0,0 +1 @@ +console.log("Hi :)"); diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/out-files/module2/lib/index.js b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/out-files/module2/lib/index.js new file mode 100644 index 000000000000..f66c36a515a9 --- /dev/null +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/out-files/module2/lib/index.js @@ -0,0 +1 @@ +let str = "Hi :)"; diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/out-files/module2/lib/main.js b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/out-files/module2/lib/main.js new file mode 100644 index 000000000000..b0d766e0fe27 --- /dev/null +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/out-files/module2/lib/main.js @@ -0,0 +1 @@ +console.log("Hi :)"); diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/stdout.txt b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/stdout.txt new file mode 100644 index 000000000000..8afbc224e55b --- /dev/null +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch multiple dir/stdout.txt @@ -0,0 +1,2 @@ +Successfully compiled 4 files with Babel (123ms). +Successfully compiled 1 file with Babel (123ms). diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch with external dependencies/executor.js b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch with external dependencies/executor.js index 474cd214405c..29730dc333e3 100644 --- a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch with external dependencies/executor.js +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch with external dependencies/executor.js @@ -4,29 +4,30 @@ const assert = require("assert"); // For Node.js <= 10 if (!assert.match) assert.match = (val, re) => assert(re.test(val)); -const run = function* () { +const run = (async function* () { assert.match(yield, /Successfully compiled 2 files with Babel \(\d+ms\)\./); logFile("lib/index.js"); logFile("lib/main.js"); - + // wait 200ms for watcher setup + await new Promise(resolve => setTimeout(resolve, 200)); fs.writeFileSync("./file.txt", "Updated!"); assert.match(yield, /Successfully compiled 2 files with Babel \(\d+ms\)\./); logFile("lib/index.js"); logFile("lib/main.js"); -}(); +})(); run.next(); -process.stdin.on("data", function listener(chunk) { +process.stdin.on("data", async function listener(chunk) { const str = String(chunk).trim(); if (!str) return; console.log(str); - if (run.next(str).done) { + if ((await run.next(str)).done) { process.exit(0); } }); diff --git a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch with external dependencies/options.json b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch with external dependencies/options.json index 290c3dcabb24..bb43a72b2540 100644 --- a/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch with external dependencies/options.json +++ b/packages/babel-cli/test/fixtures/babel/dir --out-dir --watch with external dependencies/options.json @@ -2,5 +2,5 @@ "args": ["src", "--out-dir", "lib", "--watch"], "noBabelrc": true, "noDefaultPlugins": true, - "minNodeVersion": 8 + "minNodeVersion": 10 }