Skip to content

Commit c4dc52e

Browse files
authored
cli: handle multiple input sources in watch mode (#14281)
1 parent 300e477 commit c4dc52e

File tree

18 files changed

+152
-35
lines changed

18 files changed

+152
-35
lines changed

packages/babel-cli/src/babel/dir.ts

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -177,34 +177,70 @@ export default async function ({
177177
// This, alongside with debounce, allows us to only log
178178
// when we are sure that all the files have been compiled.
179179
let processing = 0;
180+
const { filenames } = cliOptions;
181+
let getBase;
182+
if (filenames.length === 1) {
183+
// fast path: If there is only one filenames, we know it must be the base
184+
const base = filenames[0];
185+
const absoluteBase = path.resolve(base);
186+
getBase = filename => {
187+
return filename === absoluteBase ? path.dirname(base) : base;
188+
};
189+
} else {
190+
// A map from absolute compiled file path to its base, from which
191+
// the output destination will be determined
192+
const filenameToBaseMap: Map<string, string> = new Map(
193+
filenames.map(filename => {
194+
const absoluteFilename = path.resolve(filename);
195+
return [absoluteFilename, path.dirname(filename)];
196+
}),
197+
);
198+
199+
const absoluteFilenames: Map<string, string> = new Map(
200+
filenames.map(filename => {
201+
const absoluteFilename = path.resolve(filename);
202+
return [absoluteFilename, filename];
203+
}),
204+
);
205+
206+
const { sep } = path;
207+
// determine base from the absolute file path
208+
getBase = filename => {
209+
const base = filenameToBaseMap.get(filename);
210+
if (base !== undefined) {
211+
return base;
212+
}
213+
for (const [absoluteFilenameOrDir, relative] of absoluteFilenames) {
214+
if (filename.startsWith(absoluteFilenameOrDir + sep)) {
215+
filenameToBaseMap.set(filename, relative);
216+
return relative;
217+
}
218+
}
219+
// Can't determine the base, probably external deps
220+
return "";
221+
};
222+
}
180223

181-
cliOptions.filenames.forEach(filenameOrDir => {
224+
filenames.forEach(filenameOrDir => {
182225
watcher.watch(filenameOrDir);
226+
});
183227

184-
watcher.onFilesChange(async filenames => {
185-
processing++;
186-
if (startTime === null) startTime = process.hrtime();
187-
188-
try {
189-
const written = await Promise.all(
190-
filenames.map(filename =>
191-
handleFile(
192-
filename,
193-
filename === filenameOrDir
194-
? path.dirname(filenameOrDir)
195-
: filenameOrDir,
196-
),
197-
),
198-
);
199-
200-
compiledFiles += written.filter(Boolean).length;
201-
} catch (err) {
202-
console.error(err);
203-
}
228+
watcher.onFilesChange(async filenames => {
229+
processing++;
230+
if (startTime === null) startTime = process.hrtime();
204231

205-
processing--;
206-
if (processing === 0 && !cliOptions.quiet) logSuccess();
207-
});
232+
try {
233+
const written = await Promise.all(
234+
filenames.map(filename => handleFile(filename, getBase(filename))),
235+
);
236+
237+
compiledFiles += written.filter(Boolean).length;
238+
} catch (err) {
239+
console.error(err);
240+
}
241+
242+
processing--;
243+
if (processing === 0 && !cliOptions.quiet) logSuccess();
208244
});
209245
}
210246
}

packages/babel-cli/test/fixtures/babel/dir --out-dir --watch --verbose with external dependencies/executor.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ const assert = require("assert");
44
// For Node.js <= 10
55
if (!assert.match) assert.match = (val, re) => assert(re.test(val));
66

7-
const run = (function* () {
7+
const run = (async function* () {
88
let files = [yield, yield].sort();
99
assert.match(files[0], /src[\\/]index.js -> lib[\\/]index.js/);
1010
assert.match(files[1], /src[\\/]main.js -> lib[\\/]main.js/);
1111
assert.match(yield, /Successfully compiled 2 files with Babel \(\d+ms\)\./);
1212

1313
logFile("lib/index.js");
1414
logFile("lib/main.js");
15-
15+
// wait 200ms for watcher setup
16+
await new Promise(resolve => setTimeout(resolve, 200));
1617
fs.writeFileSync("./file.txt", "Updated!");
1718

1819
files = [yield, yield].sort();
@@ -29,7 +30,7 @@ run.next();
2930
const batchedStrings = [];
3031
let batchId = 0;
3132

32-
process.stdin.on("data", function listener(chunk) {
33+
process.stdin.on("data", async function listener(chunk) {
3334
const str = String(chunk).trim();
3435
if (!str) return;
3536

@@ -50,7 +51,7 @@ process.stdin.on("data", function listener(chunk) {
5051
console.log(str);
5152
}
5253

53-
if (run.next(str).done) {
54+
if ((await run.next(str)).done) {
5455
process.exit(0);
5556
}
5657
});

packages/babel-cli/test/fixtures/babel/dir --out-dir --watch --verbose with external dependencies/options.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"args": ["src", "--out-dir", "lib", "--watch", "--verbose"],
33
"noBabelrc": true,
44
"noDefaultPlugins": true,
5-
"minNodeVersion": 8
5+
"minNodeVersion": 10
66
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const fs = require("fs");
2+
const assert = require("assert");
3+
4+
// For Node.js <= 10
5+
if (!assert.match) assert.match = (val, re) => assert(re.test(val));
6+
7+
const run = (async function* () {
8+
assert.match(yield, /Successfully compiled 4 files with Babel \(\d+ms\)\./);
9+
10+
// wait 200ms for watcher setup
11+
await new Promise(resolve => setTimeout(resolve, 200));
12+
// update ./module1/src/index.js
13+
fs.writeFileSync(
14+
"./module1/src/index.js",
15+
`let str = REPLACE_ME + REPLACE_ME;`
16+
);
17+
18+
assert.match(yield, /Successfully compiled 1 file with Babel \(\d+ms\)\./);
19+
})();
20+
21+
run.next();
22+
23+
process.stdin.on("data", async function listener(chunk) {
24+
const str = String(chunk).trim();
25+
if (!str) return;
26+
27+
console.log(str);
28+
29+
if ((await run.next(str)).done) {
30+
process.exit(0);
31+
}
32+
});
33+
34+
setTimeout(() => {
35+
console.error("EXECUTOR TIMEOUT");
36+
process.exit(1);
37+
}, 5000);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const fs = require("fs");
2+
const path = require("path");
3+
4+
function inlinePlugin(api, { filename }) {
5+
const { types: t } = api;
6+
7+
const contents = api.cache.using(() => fs.readFileSync(filename, "utf8"));
8+
api.addExternalDependency(filename);
9+
10+
return {
11+
visitor: {
12+
Identifier(path) {
13+
if (path.node.name === "REPLACE_ME") {
14+
path.replaceWith(t.stringLiteral(contents));
15+
}
16+
},
17+
},
18+
};
19+
}
20+
21+
module.exports = {
22+
plugins: [
23+
[inlinePlugin, { filename: path.resolve(__dirname, "./file.txt") }],
24+
],
25+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hi :)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
let str = REPLACE_ME;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log(REPLACE_ME);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
let str = REPLACE_ME;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log(REPLACE_ME);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy