Skip to content

Commit 893e2cf

Browse files
authored
watch: fix some node argument not passed to watched process
PR-URL: #52358 Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Jacob Smith <jacob@frende.me> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
1 parent 2c77be5 commit 893e2cf

File tree

2 files changed

+184
-11
lines changed

2 files changed

+184
-11
lines changed

lib/internal/main/watch_mode.js

+24-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
'use strict';
22
const {
3-
ArrayPrototypeFilter,
43
ArrayPrototypeForEach,
54
ArrayPrototypeJoin,
65
ArrayPrototypeMap,
6+
ArrayPrototypePush,
77
ArrayPrototypePushApply,
88
ArrayPrototypeSlice,
9+
StringPrototypeIncludes,
910
StringPrototypeStartsWith,
1011
} = primordials;
1112

@@ -37,11 +38,21 @@ const kWatchedPaths = ArrayPrototypeMap(getOptionValue('--watch-path'), (path) =
3738
const kPreserveOutput = getOptionValue('--watch-preserve-output');
3839
const kCommand = ArrayPrototypeSlice(process.argv, 1);
3940
const kCommandStr = inspect(ArrayPrototypeJoin(kCommand, ' '));
40-
const args = ArrayPrototypeFilter(process.execArgv, (arg, i, arr) =>
41-
!StringPrototypeStartsWith(arg, '--watch-path') &&
42-
(!arr[i - 1] || !StringPrototypeStartsWith(arr[i - 1], '--watch-path')) &&
43-
arg !== '--watch' && !StringPrototypeStartsWith(arg, '--watch=') && arg !== '--watch-preserve-output');
44-
ArrayPrototypePushApply(args, kCommand);
41+
42+
const argsWithoutWatchOptions = [];
43+
44+
for (let i = 0; i < process.execArgv.length; i++) {
45+
const arg = process.execArgv[i];
46+
if (StringPrototypeStartsWith(arg, '--watch')) {
47+
if (!StringPrototypeIncludes(arg, '=')) {
48+
i++;
49+
}
50+
continue;
51+
}
52+
ArrayPrototypePush(argsWithoutWatchOptions, arg);
53+
}
54+
55+
ArrayPrototypePushApply(argsWithoutWatchOptions, kCommand);
4556

4657
const watcher = new FilesWatcher({ debounce: 200, mode: kShouldFilterModules ? 'filter' : 'all' });
4758
ArrayPrototypeForEach(kWatchedPaths, (p) => watcher.watchPath(p));
@@ -53,7 +64,13 @@ let exited;
5364
function start() {
5465
exited = false;
5566
const stdio = kShouldFilterModules ? ['inherit', 'inherit', 'inherit', 'ipc'] : 'inherit';
56-
child = spawn(process.execPath, args, { stdio, env: { ...process.env, WATCH_REPORT_DEPENDENCIES: '1' } });
67+
child = spawn(process.execPath, argsWithoutWatchOptions, {
68+
stdio,
69+
env: {
70+
...process.env,
71+
WATCH_REPORT_DEPENDENCIES: '1',
72+
},
73+
});
5774
watcher.watchChildProcessModules(child);
5875
child.once('exit', (code) => {
5976
exited = true;

test/sequential/test-watch-mode.mjs

+160-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,14 @@ function createTmpFile(content = 'console.log("running");', ext = '.js', basenam
3030
}
3131

3232
async function runWriteSucceed({
33-
file, watchedFile, watchFlag = '--watch', args = [file], completed = 'Completed running', restarts = 2, options = {}
33+
file,
34+
watchedFile,
35+
watchFlag = '--watch',
36+
args = [file],
37+
completed = 'Completed running',
38+
restarts = 2,
39+
options = {},
40+
shouldFail = false
3441
}) {
3542
const child = spawn(execPath, [watchFlag, '--no-warnings', ...args], { encoding: 'utf8', stdio: 'pipe', ...options });
3643
let completes = 0;
@@ -57,6 +64,10 @@ async function runWriteSucceed({
5764
cancelRestarts = restart(watchedFile);
5865
}
5966
}
67+
68+
if (!shouldFail && data.startsWith('Failed running')) {
69+
break;
70+
}
6071
}
6172
} finally {
6273
child.kill();
@@ -120,7 +131,12 @@ describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_00
120131

121132
it('should watch changes to a failing file', async () => {
122133
const file = createTmpFile('throw new Error("fails");');
123-
const { stderr, stdout } = await runWriteSucceed({ file, watchedFile: file, completed: 'Failed running' });
134+
const { stderr, stdout } = await runWriteSucceed({
135+
file,
136+
watchedFile: file,
137+
completed: 'Failed running',
138+
shouldFail: true
139+
});
124140

125141
assert.match(stderr, /Error: fails\r?\n/);
126142
assert.deepStrictEqual(stdout, [
@@ -159,7 +175,13 @@ describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_00
159175
const file = path.join(dir, 'non-existing.js');
160176
const watchedFile = createTmpFile('', '.js', dir);
161177
const args = ['--watch-path', dir, file];
162-
const { stderr, stdout } = await runWriteSucceed({ file, watchedFile, args, completed: 'Failed running' });
178+
const { stderr, stdout } = await runWriteSucceed({
179+
file,
180+
watchedFile,
181+
args,
182+
completed: 'Failed running',
183+
shouldFail: true
184+
});
163185

164186
assert.match(stderr, /Error: Cannot find module/g);
165187
assert.deepStrictEqual(stdout, [
@@ -177,7 +199,13 @@ describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_00
177199
const file = path.join(dir, 'non-existing.js');
178200
const watchedFile = createTmpFile('', '.js', dir);
179201
const args = [`--watch-path=${dir}`, file];
180-
const { stderr, stdout } = await runWriteSucceed({ file, watchedFile, args, completed: 'Failed running' });
202+
const { stderr, stdout } = await runWriteSucceed({
203+
file,
204+
watchedFile,
205+
args,
206+
completed: 'Failed running',
207+
shouldFail: true
208+
});
181209

182210
assert.match(stderr, /Error: Cannot find module/g);
183211
assert.deepStrictEqual(stdout, [
@@ -372,4 +400,132 @@ console.log(values.random);
372400
`Completed running ${inspect(file)}`,
373401
]);
374402
});
403+
404+
it('should run when `--watch-path=./foo --require ./bar.js`', {
405+
skip: !supportsRecursive,
406+
}, async () => {
407+
const projectDir = tmpdir.resolve('project2');
408+
mkdirSync(projectDir);
409+
410+
const dir = path.join(projectDir, 'watched-dir');
411+
mkdirSync(dir);
412+
413+
writeFileSync(path.join(projectDir, 'some.js'), 'console.log(\'hello\')');
414+
415+
const file = createTmpFile('console.log(\'running\');', '.js', projectDir);
416+
const watchedFile = createTmpFile('', '.js', dir);
417+
const args = [`--watch-path=${dir}`, '--require', './some.js', file];
418+
const { stdout, stderr } = await runWriteSucceed({
419+
file, watchedFile, args, options: {
420+
cwd: projectDir
421+
}
422+
});
423+
424+
assert.strictEqual(stderr, '');
425+
assert.deepStrictEqual(stdout, [
426+
'hello',
427+
'running',
428+
`Completed running ${inspect(file)}`,
429+
`Restarting ${inspect(file)}`,
430+
'hello',
431+
'running',
432+
`Completed running ${inspect(file)}`,
433+
]);
434+
});
435+
436+
it('should run when `--watch-path=./foo --require=./bar.js`', {
437+
skip: !supportsRecursive,
438+
}, async () => {
439+
const projectDir = tmpdir.resolve('project3');
440+
mkdirSync(projectDir);
441+
442+
const dir = path.join(projectDir, 'watched-dir');
443+
mkdirSync(dir);
444+
445+
writeFileSync(path.join(projectDir, 'some.js'), "console.log('hello')");
446+
447+
const file = createTmpFile("console.log('running');", '.js', projectDir);
448+
const watchedFile = createTmpFile('', '.js', dir);
449+
const args = [`--watch-path=${dir}`, '--require=./some.js', file];
450+
const { stdout, stderr } = await runWriteSucceed({
451+
file, watchedFile, args, options: {
452+
cwd: projectDir
453+
}
454+
});
455+
456+
assert.strictEqual(stderr, '');
457+
assert.deepStrictEqual(stdout, [
458+
'hello',
459+
'running',
460+
`Completed running ${inspect(file)}`,
461+
`Restarting ${inspect(file)}`,
462+
'hello',
463+
'running',
464+
`Completed running ${inspect(file)}`,
465+
]);
466+
});
467+
468+
it('should run when `--watch-path ./foo --require ./bar.js`', {
469+
skip: !supportsRecursive,
470+
}, async () => {
471+
const projectDir = tmpdir.resolve('project5');
472+
mkdirSync(projectDir);
473+
474+
const dir = path.join(projectDir, 'watched-dir');
475+
mkdirSync(dir);
476+
477+
writeFileSync(path.join(projectDir, 'some.js'), 'console.log(\'hello\')');
478+
479+
const file = createTmpFile('console.log(\'running\');', '.js', projectDir);
480+
const watchedFile = createTmpFile('', '.js', dir);
481+
const args = ['--watch-path', `${dir}`, '--require', './some.js', file];
482+
const { stdout, stderr } = await runWriteSucceed({
483+
file, watchedFile, args, options: {
484+
cwd: projectDir
485+
}
486+
});
487+
488+
assert.strictEqual(stderr, '');
489+
assert.deepStrictEqual(stdout, [
490+
'hello',
491+
'running',
492+
`Completed running ${inspect(file)}`,
493+
`Restarting ${inspect(file)}`,
494+
'hello',
495+
'running',
496+
`Completed running ${inspect(file)}`,
497+
]);
498+
});
499+
500+
it('should run when `--watch-path=./foo --require=./bar.js`', {
501+
skip: !supportsRecursive,
502+
}, async () => {
503+
const projectDir = tmpdir.resolve('project6');
504+
mkdirSync(projectDir);
505+
506+
const dir = path.join(projectDir, 'watched-dir');
507+
mkdirSync(dir);
508+
509+
writeFileSync(path.join(projectDir, 'some.js'), "console.log('hello')");
510+
511+
const file = createTmpFile("console.log('running');", '.js', projectDir);
512+
const watchedFile = createTmpFile('', '.js', dir);
513+
const args = ['--watch-path', `${dir}`, '--require=./some.js', file];
514+
const { stdout, stderr } = await runWriteSucceed({
515+
file, watchedFile, args, options: {
516+
cwd: projectDir
517+
}
518+
});
519+
520+
assert.strictEqual(stderr, '');
521+
assert.deepStrictEqual(stdout, [
522+
'hello',
523+
'running',
524+
`Completed running ${inspect(file)}`,
525+
`Restarting ${inspect(file)}`,
526+
'hello',
527+
'running',
528+
`Completed running ${inspect(file)}`,
529+
]);
530+
});
375531
});

0 commit comments

Comments
 (0)