mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
watch: fix watch args not being properly filtered
currently when --watch is used, the argv arguments that the target script receives are filtered so that they don't include watch related arguments, however the current filtering logic is incorrect and it causes some watch values to incorrectly pass the filtering, the changes here address such issue PR-URL: https://github.com/nodejs/node/pull/58279 Fixes: https://github.com/nodejs/node/issues/57124 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
@@ -43,11 +43,26 @@ const argsWithoutWatchOptions = [];
|
||||
|
||||
for (let i = 0; i < process.execArgv.length; i++) {
|
||||
const arg = process.execArgv[i];
|
||||
if (StringPrototypeStartsWith(arg, '--watch')) {
|
||||
i++;
|
||||
const nextArg = process.execArgv[i];
|
||||
if (nextArg && nextArg[0] === '-') {
|
||||
ArrayPrototypePush(argsWithoutWatchOptions, nextArg);
|
||||
if (StringPrototypeStartsWith(arg, '--watch=')) {
|
||||
continue;
|
||||
}
|
||||
if (arg === '--watch') {
|
||||
const nextArg = process.execArgv[i + 1];
|
||||
if (nextArg && nextArg[0] !== '-') {
|
||||
// If `--watch` doesn't include `=` and the next
|
||||
// argument is not a flag then it is interpreted as
|
||||
// the watch argument, so we need to skip that as well
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (StringPrototypeStartsWith(arg, '--watch-path')) {
|
||||
const lengthOfWatchPathStr = 12;
|
||||
if (arg[lengthOfWatchPathStr] !== '=') {
|
||||
// if --watch-path doesn't include `=` it means
|
||||
// that the next arg is the target path, so we
|
||||
// need to skip that as well
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
97
test/sequential/test-watch-mode-watch-flags.mjs
Normal file
97
test/sequential/test-watch-mode-watch-flags.mjs
Normal file
@@ -0,0 +1,97 @@
|
||||
import * as common from '../common/index.mjs';
|
||||
import tmpdir from '../common/tmpdir.js';
|
||||
import assert from 'node:assert';
|
||||
import path from 'node:path';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
import { spawn } from 'node:child_process';
|
||||
import { writeFileSync, mkdirSync } from 'node:fs';
|
||||
import { inspect } from 'node:util';
|
||||
import { createInterface } from 'node:readline';
|
||||
|
||||
if (common.isIBMi)
|
||||
common.skip('IBMi does not support `fs.watch()`');
|
||||
|
||||
let tmpFiles = 0;
|
||||
function createTmpFile(content, ext, basename) {
|
||||
const file = path.join(basename, `${tmpFiles++}${ext}`);
|
||||
writeFileSync(file, content);
|
||||
return file;
|
||||
}
|
||||
|
||||
async function runNode({
|
||||
args,
|
||||
expectedCompletionLog = 'Completed running',
|
||||
options = {},
|
||||
}) {
|
||||
const child = spawn(execPath, args, { encoding: 'utf8', stdio: 'pipe', ...options });
|
||||
let stderr = '';
|
||||
const stdout = [];
|
||||
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
|
||||
try {
|
||||
// Break the chunks into lines
|
||||
for await (const data of createInterface({ input: child.stdout })) {
|
||||
if (!data.startsWith('Waiting for graceful termination') && !data.startsWith('Gracefully restarted')) {
|
||||
stdout.push(data);
|
||||
}
|
||||
if (data.startsWith(expectedCompletionLog)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
child.kill();
|
||||
}
|
||||
return { stdout, stderr, pid: child.pid };
|
||||
}
|
||||
|
||||
tmpdir.refresh();
|
||||
|
||||
describe('watch mode - watch flags', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_000 }, () => {
|
||||
it('when multiple `--watch` flags are provided should run as if only one was', async () => {
|
||||
const projectDir = tmpdir.resolve('project-multi-flag');
|
||||
mkdirSync(projectDir);
|
||||
|
||||
const file = createTmpFile(`
|
||||
console.log(
|
||||
process.argv.some(arg => arg === '--watch')
|
||||
? 'Error: unexpected --watch args present'
|
||||
: 'no --watch args present'
|
||||
);`, '.js', projectDir);
|
||||
const args = ['--watch', '--watch', file];
|
||||
const { stdout, stderr } = await runNode({
|
||||
file, args, options: { cwd: projectDir }
|
||||
});
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.deepStrictEqual(stdout, [
|
||||
'no --watch args present',
|
||||
`Completed running ${inspect(file)}. Waiting for file changes before restarting...`,
|
||||
]);
|
||||
});
|
||||
|
||||
it('`--watch-path` args without `=` used alongside `--watch` should not make it into the script', async () => {
|
||||
const projectDir = tmpdir.resolve('project-watch-watch-path-args');
|
||||
mkdirSync(projectDir);
|
||||
|
||||
const file = createTmpFile(`
|
||||
console.log(
|
||||
process.argv.slice(2).some(arg => arg.endsWith('.js'))
|
||||
? 'some cli args end with .js'
|
||||
: 'no cli arg ends with .js'
|
||||
);`, '.js', projectDir);
|
||||
const args = ['--watch', `--watch-path`, file, file];
|
||||
const { stdout, stderr } = await runNode({
|
||||
file, args, options: { cwd: projectDir }
|
||||
});
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.deepStrictEqual(stdout, [
|
||||
'no cli arg ends with .js',
|
||||
`Completed running ${inspect(file)}. Waiting for file changes before restarting...`,
|
||||
]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user