From 053ef2e2bed55c90257fdb9db9009b260e5335e0 Mon Sep 17 00:00:00 2001 From: marcopiraccini Date: Sun, 7 Jun 2026 08:12:46 +0200 Subject: [PATCH] watch: print name of changed file that triggers restart Signed-off-by: marcopiraccini --- lib/internal/main/watch_mode.js | 9 +++-- lib/internal/watch_mode/files_watcher.js | 6 +++- ...t-watch-mode-restart-esm-loading-error.mjs | 2 ++ test/sequential/test-watch-mode-worker.mjs | 10 ++++++ test/sequential/test-watch-mode.mjs | 33 +++++++++++++++++++ 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/lib/internal/main/watch_mode.js b/lib/internal/main/watch_mode.js index ba441a960f07d1..d36dccfc3dd239 100644 --- a/lib/internal/main/watch_mode.js +++ b/lib/internal/main/watch_mode.js @@ -169,11 +169,14 @@ async function stop(child) { let restarting = false; -async function restart(child) { +async function restart(child, trigger) { if (restarting) return; restarting = true; try { if (!kPreserveOutput) process.stdout.write(clear); + if (trigger) { + process.stdout.write(`${blue}Change detected in ${inspect(trigger)}${white}\n`); + } process.stdout.write(`${green}Restarting ${kCommandStr}${white}\n`); await stop(child); return start(); @@ -184,8 +187,8 @@ async function restart(child) { async function init() { let child = start(); - const restartChild = async () => { - child = await restart(child); + const restartChild = async ({ trigger } = {}) => { + child = await restart(child, trigger); }; watcher .on('changed', restartChild) diff --git a/lib/internal/watch_mode/files_watcher.js b/lib/internal/watch_mode/files_watcher.js index c94775b3e6e4bc..c87f489b63771a 100644 --- a/lib/internal/watch_mode/files_watcher.js +++ b/lib/internal/watch_mode/files_watcher.js @@ -39,6 +39,7 @@ class FilesWatcher extends EventEmitter { #ownerDependencies = new SafeMap(); #debounceOwners = new SafeSet(); #debounceTimer; + #debounceTrigger; #debounce; #mode; #signal; @@ -98,11 +99,13 @@ class FilesWatcher extends EventEmitter { this.#debounceOwners.add(owner); } } + this.#debounceTrigger = trigger; clearTimeout(this.#debounceTimer); this.#debounceTimer = setTimeout(() => { this.#debounceTimer = null; - this.emit('changed', { owners: this.#debounceOwners, eventType }); + this.emit('changed', { owners: this.#debounceOwners, eventType, trigger: this.#debounceTrigger }); this.#debounceOwners.clear(); + this.#debounceTrigger = undefined; }, this.#debounce).unref(); } @@ -207,6 +210,7 @@ class FilesWatcher extends EventEmitter { clearTimeout(this.#debounceTimer); this.#debounceTimer = null; this.#debounceOwners.clear(); + this.#debounceTrigger = undefined; this.#watchers.forEach(this.#unwatch); this.#watchers.clear(); this.#filteredFiles.clear(); diff --git a/test/sequential/test-watch-mode-restart-esm-loading-error.mjs b/test/sequential/test-watch-mode-restart-esm-loading-error.mjs index 95a62423160af9..1d1b954588c543 100644 --- a/test/sequential/test-watch-mode-restart-esm-loading-error.mjs +++ b/test/sequential/test-watch-mode-restart-esm-loading-error.mjs @@ -120,6 +120,7 @@ try { const { stderr: stderr2, stdout: stdout2 } = await failedRestart; assert.match(stderr2, /SyntaxError: Invalid or unexpected token/); assert.deepStrictEqual(stdout2, [ + `Change detected in ${inspect(file)}`, `Restarting ${inspect(file)}`, `Failed running ${inspect(file)}. Waiting for file changes before restarting...`, ]); @@ -132,6 +133,7 @@ try { // Verify it recovered and ran successfully assert.strictEqual(stderr3, ''); assert.deepStrictEqual(stdout3, [ + `Change detected in ${inspect(file)}`, `Restarting ${inspect(file)}`, 'hello again, world', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, diff --git a/test/sequential/test-watch-mode-worker.mjs b/test/sequential/test-watch-mode-worker.mjs index 41cdf05782cd38..330ecbeddfc42a 100644 --- a/test/sequential/test-watch-mode-worker.mjs +++ b/test/sequential/test-watch-mode-worker.mjs @@ -19,6 +19,10 @@ function restart(file) { return () => clearInterval(timer); } +function changeDetected(file) { + return `Change detected in ${inspect(file)}`; +} + let tmpFiles = 0; function createTmpFile(content = 'console.log(\'running\');', ext = '.js', basename = tmpdir.path) { const file = path.join(basename, `${tmpFiles++}${ext}`); @@ -108,6 +112,7 @@ const w = new Worker(${JSON.stringify(worker)}); assert.deepStrictEqual(stdout, [ 'worker running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(worker), `Restarting ${inspect(file)}`, 'worker running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -142,6 +147,7 @@ const w = new Worker(${JSON.stringify(worker)}); assert.deepStrictEqual(stdout, [ 'dep v1', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(dep), `Restarting ${inspect(file)}`, 'dep v1', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -182,6 +188,7 @@ const w = new Worker(${JSON.stringify(worker)}); assert.deepStrictEqual(stdout, [ 'sub-dep v1', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(subDep), `Restarting ${inspect(file)}`, 'sub-dep v1', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -210,6 +217,7 @@ new Worker(new URL(${JSON.stringify(pathToFileURL(worker))})); assert.deepStrictEqual(stdout, [ 'worker running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(worker), `Restarting ${inspect(file)}`, 'worker running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -244,6 +252,7 @@ new Worker(new URL(${JSON.stringify(pathToFileURL(worker))})); assert.deepStrictEqual(stdout, [ 'dep v1', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(dep), `Restarting ${inspect(file)}`, 'dep v1', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -284,6 +293,7 @@ new Worker(new URL(${JSON.stringify(pathToFileURL(worker))})); assert.deepStrictEqual(stdout, [ 'sub-dep v1', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(subDep), `Restarting ${inspect(file)}`, 'sub-dep v1', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, diff --git a/test/sequential/test-watch-mode.mjs b/test/sequential/test-watch-mode.mjs index 5b9c789343daa9..54132b7f81cc19 100644 --- a/test/sequential/test-watch-mode.mjs +++ b/test/sequential/test-watch-mode.mjs @@ -23,6 +23,10 @@ function restart(file, content = readFileSync(file)) { return () => clearInterval(timer); } +function changeDetected(file) { + return `Change detected in ${inspect(file)}`; +} + let tmpFiles = 0; function createTmpFile(content = 'console.log("running");', ext = '.js', basename = tmpdir.path) { const file = path.join(basename, `${tmpFiles++}${ext}`); @@ -198,6 +202,7 @@ describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_00 assert.deepStrictEqual(stdout, [ 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(file), `Restarting ${inspect(file)}`, 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -212,6 +217,7 @@ describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_00 assert.deepStrictEqual(stdout, [ 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(file), `Restarting ${inspect(file)}`, 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -233,6 +239,7 @@ describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_00 assert.strictEqual(stderr, ''); assert.deepStrictEqual(stdout, [ + changeDetected(envFile), `Restarting ${inspect(jsFile)}`, 'ENV: value2', `Completed running ${inspect(jsFile)}. Waiting for file changes before restarting...`, @@ -258,6 +265,7 @@ describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_00 assert.strictEqual(stderr, ''); assert.deepStrictEqual(stdout, [ + changeDetected(envFile), `Restarting ${inspect(jsFile)}`, 'ENV: value1', 'ENV2: newValue', @@ -284,6 +292,7 @@ describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_00 assert.strictEqual(stderr, ''); assert.deepStrictEqual(stdout, [ + changeDetected(envFile), `Restarting ${inspect(jsFile)}`, 'ENV: value1', 'ENV2: newValue', @@ -327,6 +336,7 @@ describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_00 assert.match(stderr, /Error: fails\r?\n/); assert.deepStrictEqual(stdout, [ `Failed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(file), `Restarting ${inspect(file)}`, `Failed running ${inspect(file)}. Waiting for file changes before restarting...`, ]); @@ -346,6 +356,7 @@ describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_00 assert.deepStrictEqual(stdout, [ 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(watchedFile), `Restarting ${inspect(file)}`, 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -372,6 +383,7 @@ describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_00 assert.match(stderr, /Error: Cannot find module/g); assert.deepStrictEqual(stdout, [ `Failed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(watchedFile), `Restarting ${inspect(file)}`, `Failed running ${inspect(file)}. Waiting for file changes before restarting...`, ]); @@ -396,6 +408,7 @@ describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_00 assert.match(stderr, /Error: Cannot find module/g); assert.deepStrictEqual(stdout, [ `Failed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(watchedFile), `Restarting ${inspect(file)}`, `Failed running ${inspect(file)}. Waiting for file changes before restarting...`, ]); @@ -411,6 +424,7 @@ console.log("don't show me");`); assert.strictEqual(stderr, ''); assert.deepStrictEqual(stdout, [ 'running', + changeDetected(file), `Restarting ${inspect(file)}`, 'running', ]); @@ -428,6 +442,7 @@ console.log(dependency); assert.deepStrictEqual(stdout, [ '{}', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(dependency), `Restarting ${inspect(file)}`, '{}', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -446,6 +461,7 @@ console.log(dependency); assert.deepStrictEqual(stdout, [ '{}', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(dependency), `Restarting ${inspect(file)}`, '{}', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -460,9 +476,11 @@ console.log(dependency); assert.deepStrictEqual(stdout, [ 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(file), `Restarting ${inspect(file)}`, 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(file), `Restarting ${inspect(file)}`, 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -483,6 +501,7 @@ console.log(values.random); assert.deepStrictEqual(stdout, [ random, `Completed running ${inspect(`${file} --random ${random}`)}. Waiting for file changes before restarting...`, + changeDetected(file), `Restarting ${inspect(`${file} --random ${random}`)}`, random, `Completed running ${inspect(`${file} --random ${random}`)}. Waiting for file changes before restarting...`, @@ -500,6 +519,7 @@ console.log(values.random); assert.deepStrictEqual(stdout, [ 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(file), `Restarting ${inspect(file)}`, 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -520,6 +540,7 @@ console.log(values.random); assert.deepStrictEqual(stdout, [ 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(file), `Restarting ${inspect(file)}`, 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -569,6 +590,7 @@ console.log(values.random); assert.deepStrictEqual(stdout, [ 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(file), `Restarting ${inspect(file)}`, 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -584,6 +606,7 @@ console.log(values.random); assert.deepStrictEqual(stdout, [ 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(file), `Restarting ${inspect(file)}`, 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -615,6 +638,7 @@ console.log(values.random); 'hello', 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(watchedFile), `Restarting ${inspect(file)}`, 'hello', 'running', @@ -647,6 +671,7 @@ console.log(values.random); 'hello', 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(watchedFile), `Restarting ${inspect(file)}`, 'hello', 'running', @@ -679,6 +704,7 @@ console.log(values.random); 'hello', 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(watchedFile), `Restarting ${inspect(file)}`, 'hello', 'running', @@ -711,6 +737,7 @@ console.log(values.random); 'hello', 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(watchedFile), `Restarting ${inspect(file)}`, 'hello', 'running', @@ -727,6 +754,7 @@ console.log(values.random); assert.deepStrictEqual(stdout, [ 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(file), `Restarting ${inspect(file)}`, 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -752,6 +780,7 @@ console.log(values.random); 'hello', 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(file), `Restarting ${inspect(file)}`, 'hello', 'running', @@ -832,6 +861,7 @@ process.on('message', (message) => { assert.deepStrictEqual(lines, [ 'running', 'Received: first message', + changeDetected(file), `Restarting ${inspect(file)}`, 'running', 'Received: second message', @@ -852,6 +882,7 @@ process.on('message', (message) => { assert.deepStrictEqual(stdout, [ 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(file), `Restarting ${inspect(file)}`, 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -874,6 +905,7 @@ process.on('message', (message) => { assert.deepStrictEqual(stdout, [ 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(watchedFile), `Restarting ${inspect(file)}`, 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, @@ -902,6 +934,7 @@ process.on('message', (message) => { assert.deepStrictEqual(stdout, [ 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`, + changeDetected(file), `Restarting ${inspect(file)}`, 'running', `Completed running ${inspect(file)}. Waiting for file changes before restarting...`,