Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

watch: add CLI flag to preserve output #45717

Merged
merged 12 commits into from Dec 11, 2022
9 changes: 9 additions & 0 deletions doc/api/cli.md
Expand Up @@ -1628,6 +1628,14 @@ This option is only supported on macOS and Windows.
An `ERR_FEATURE_UNAVAILABLE_ON_PLATFORM` exception will be thrown
when the option is used on a platform that does not support it.

### `--watch-preserve-output`

Disable the clearing of the console when watch mode restarts the process.

```console
$ node --watch --watch-preserve-output test.js
```

### `--zero-fill-buffers`

<!-- YAML
Expand Down Expand Up @@ -1932,6 +1940,7 @@ Node.js options that are allowed are:
* `--use-openssl-ca`
* `--v8-pool-size`
* `--watch-path`
* `--watch-preserve-output`
* `--watch`
* `--zero-fill-buffers`

Expand Down
6 changes: 4 additions & 2 deletions lib/internal/main/watch_mode.js
Expand Up @@ -34,10 +34,11 @@ markBootstrapComplete();
const kKillSignal = 'SIGTERM';
const kShouldFilterModules = getOptionValue('--watch-path').length === 0;
const kWatchedPaths = ArrayPrototypeMap(getOptionValue('--watch-path'), (path) => resolve(path));
const kPreserveOutput = getOptionValue('--watch-preserve-output');
const kCommand = ArrayPrototypeSlice(process.argv, 1);
const kCommandStr = inspect(ArrayPrototypeJoin(kCommand, ' '));
const args = ArrayPrototypeFilter(process.execArgv, (arg, i, arr) =>
arg !== '--watch-path' && arr[i - 1] !== '--watch-path' && arg !== '--watch');
arg !== '--watch-path' && arr[i - 1] !== '--watch-path' && arg !== '--watch' && arg !== '--watch-preserve-output');
ArrayPrototypePushApply(args, kCommand);

const watcher = new FilesWatcher({ throttle: 500, mode: kShouldFilterModules ? 'filter' : 'all' });
Expand Down Expand Up @@ -100,7 +101,8 @@ async function stop() {
}

async function restart() {
process.stdout.write(`${clear}${green}Restarting ${kCommandStr}${white}\n`);
if (!kPreserveOutput) process.stdout.write(clear);
process.stdout.write(`${green}Restarting ${kCommandStr}${white}\n`);
await stop();
start();
}
Expand Down
4 changes: 4 additions & 0 deletions src/node_options.cc
Expand Up @@ -613,6 +613,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
"path to watch",
&EnvironmentOptions::watch_mode_paths,
kAllowedInEnvvar);
AddOption("--watch-preserve-output",
"preserve outputs on watch mode restart",
&EnvironmentOptions::watch_mode_preserve_output,
kAllowedInEnvvar);
Implies("--watch-path", "--watch");
AddOption("--check",
"syntax check script without executing",
Expand Down
1 change: 1 addition & 0 deletions src/node_options.h
Expand Up @@ -177,6 +177,7 @@ class EnvironmentOptions : public Options {

bool watch_mode = false;
bool watch_mode_report_to_parent = false;
bool watch_mode_preserve_output = false;
std::vector<std::string> watch_mode_paths;

bool syntax_check_only = false;
Expand Down
25 changes: 25 additions & 0 deletions test/sequential/test-watch-mode.mjs
Expand Up @@ -280,4 +280,29 @@ describe('watch mode', { concurrency: false, timeout: 60_000 }, () => {

await failWriteSucceed({ file: dependant, watchedFile: dependency });
});

it('should preserve output when --watch-preserve-output flag is passed', async () => {
const file = createTmpFile();
const { stderr, stdout } = await spawnWithRestarts({
file,
args: ['--watch-preserve-output', file],
});

assert.strictEqual(stderr, '');
// Checks if the existing output is preserved
assertRestartedCorrectly({
stdout,
messages: {
inner: 'running',
restarted: `Restarting ${inspect(file)}`,
completed: `Completed running ${inspect(file)}`,
},
});
// Remove the first 3 lines from stdout
const lines = stdout.split(/\r?\n/).filter(Boolean).slice(3);
assert.deepStrictEqual(lines, [
'running',
`Completed running ${inspect(file)}`,
]);
});
});